Comments 6
При использовании этого метода обязательно проверьте, что в используемом клиенте Redis тайм-ауты действительно работают в случае отказа Redis-ов, в т.ч. в случае «молчаливого» и внезапного blackhole связи до его инстансов (привет, .Net).
Лично я давно уже использую блокировку в Redis с помощью операций INCR/DECR. Преимущества:
- Они атомарны
- Возвращают результат
Алгоритм для взятия блокировки:
- выполняем INCR по ключу
- если возвращенное значение больше 1, то блокировка не удалась — кто-то уже держит лок. Выполняем DECR.
- если INCR вернул 1, значит мы успешно получили блокировку. Дальше мы работаем с ресурсом и выполняем DECR в конце. Как вариант можно еще установить TTL на ключ чтобы в случае таймаута блокировка была снята (если мы представляем себе все последствия ошибок, связанных с этим)
Здесь мы имеем по 2 операции на блокировку (в том числе и неудачную), но зато у нас не может возникнуть race condition и нам не надо городить какие-то конструкции на lua.
Статья про распределенную блокировку, которая продолжает работать, если падает меньше половины инстансов.
Если "второй" клиент, после INCR получил > 1 и сразу же упал, или просто забил на выполнение DECR, то будет "больно" пока не кончится TTL.
А может быть ещё интереснее — второй клиент сделает свой DECR после того как первый успеет сделать свой. В итоге получим в ключе -1.
О том, как на самом деле правильно делать локи.
Распределенные блокировки с применением Redis