Как стать автором
Обновить

Распределенные блокировки с применением Redis

Время на прочтение12 мин
Количество просмотров27K
Всего голосов 10: ↑10 и ↓0+10
Комментарии6

Комментарии 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.

Нет, -1 не получится

Зарегистрируйтесь на Хабре, чтобы оставить комментарий