В документации redis я обнаружил, что примитивная блокировка может быть реализована через SETNX:
http://redis.io/commands/setnx
C4 отправляет SETNX lock.foo, чтобы получить блокировку
Аварийный клиент C3 все еще удерживает его, поэтому Redis ответит 0 на C4.
C4 отправляет GET lock.foo, чтобы проверить, истек ли срок блокировки. Если это не так, он будет спать некоторое время и повторить попытку с самого начала.
Вместо этого, если блокировка истекла, потому что время Unix в lock.foo больше, чем текущее время Unix, C4 пытается выполнить:
GETSET lock.foo
Из-за семантики GETSET C4 может проверить, сохраняется ли старое значение, хранящееся в ключе, истекшую временную метку. Если это так, замок был приобретен.
Если другой клиент, например C5, был быстрее, чем C4, и приобрел блокировку с помощью операции GETSET, операция C4 GETSET вернет отметку с истекшим сроком действия. C4 просто перезапустится с первого шага. Обратите внимание, что даже если C4 несколько раз установит ключ в несколько секунд, это не проблема.
Однако, как отмечали некоторые пользователи, использование временной отметки UNIX в качестве срока действия требует, чтобы время клиента и сервера было полностью синхронизировано. Есть ли лучшая альтернатива для создания глобальной/распределенной блокировки в Redis?