Microsoft.Web.RedisSessionStateProvider не сохраняет значение - PullRequest
0 голосов
/ 08 апреля 2019

Задача

Значение сеанса не извлекается в представлении Razor и вызывает ошибочную логику.

Окружающая среда

Redis Sentinel с часовым на веб-серверах, но только один Redis Master и один Redis Slave. Строка подключения Redis указывает и на ведущее, и на ведомое устройство.

Код

В контроллере перед просмотром:

var fooLocal = fooMapper.Map(fooDbCall.GetFromDb(fooValue));

if (fooLocal != null)
{
    Session["FooSession"] = fooLocal.fooProperty;
}
else
{
    Session["FooSession"] = false;
}

В поле зрения

@if (fooRazorVal == 123)
{
    // show some stuff
}
else if (!((bool?)Session["FooSession"] ?? false) && (fooRazorVal2 == 456))
{
    // show error message
}
else
{
    // show other stuff
}

Результат

Сообщение об ошибке отображается, даже если соответствующая учетная запись прошла через код и базу данных, чтобы проверить, что она не должна быть ложной, не говоря уже о нулевом значении. Другие значения сеанса хранятся и извлекаются нормально, иначе вы бы даже не заходили так далеко в моем процессе.

Исследование

Как я уже говорил, все остальные биты кода и база данных были проверены. Я добавил класс журналирования, и есть много записей, таких как:

[Info]GetItemFromSessionStore => Session Id: ctps3urcqwm0tpezo5bbmqzj, Session provider object: 4686063 => Can not lock, Someone else has lock and lockId is 636901606595110722
[Info]GetItemFromSessionStore => Session Id: ctps3urcqwm0tpezo5bbmqzj, Session provider object: 26422156 => Lock taken with lockId: 636901606595110722
[Info]GetItemFromSessionStore => Session Id: ctps3urcqwm0tpezo5bbmqzj, Session provider object: 4686063 => Can not lock, Someone else has lock and lockId is 636901606595110722

Однако, учитывая их огромное количество, мне интересно, действительно ли это ошибка или RedisSessionStateProvider работает так, как задумано. Я видел, что он использует SETNX для получения замков. К сожалению, я недостаточно хорошо разбираюсь в семантике redis, чтобы понять, вызывает ли это проблему.

Я см. Примечание в документации Redis о том, что это старый подход и что вместо него используется RedLock. Однако, как я понимаю RedLock, одной настройки master / single slave недостаточно, хотя она поддерживает повторные попытки, поэтому, возможно, она все равно будет работать. Мне также любопытно, стоит ли мне использовать простой пользовательский провайдер, который позволяет StackExhange ConnectionMultiplexer работать без дополнительных блокировок или пользовательских сценариев, и если мне нужны блокировки для использования одной из библиотек C # для RedLock.

1 Ответ

1 голос
/ 10 апреля 2019

По умолчанию ключи Redis блокируются во время обновления, вам не нужно их блокировать.Действительно, Redis использует один поток для обработки команд, поэтому каждая операция является атомарной.Другие клиенты блокируются во время обработки данной команды, поэтому вы не должны выполнять запросы с длительным временем выполнения, и вы получаете эту ошибку.

Чтобы предотвратить это, необходимо реализовать распределенную блокировку.Распределенные блокировки являются очень полезным примитивом во многих средах, где разные процессы должны работать с совместно используемыми ресурсами взаимоисключающим образом.

Здесь представлены разные реализации для разных языков.

Реализации

Вот несколько ссылок на уже имеющиеся реализации, которые можно использовать для справки.

Redlock-rb (реализация Ruby).Существует также форк Redlock-rb, который добавляет гем для легкого распространения и, возможно, больше.

Redlock-py (реализация Python).

Aioredlock (реализация Asyncio Python).

Redlock-php (реализация PHP).

PHPRedisMutex (дальнейшая реализация PHP)

Redsync.go (реализация Go).

Redisson (реализация Java).

Redis :: DistLock (реализация Perl).

Redlock-cpp (реализация C ++).

Redlock-cs (C # /. NET реализация).

RedLock.net (C # /. NET реализация).Включает поддержку расширений асинхронности и блокировки.

ScarletLock (реализация C # .NET с настраиваемым хранилищем данных)

node-redlock (реализация NodeJS).Включает поддержку расширения блокировки.

Проверьте, поможет ли это.

...