Discourse широко использует блокировки Redis в качестве механизма синхронизации. Реализация блокировок Redis в Discourse (показанная ниже) может быть улучшена за счёт сокращения количества команд Redis, что уменьшит время кругового обращения и затраты на их выполнение.
Как мы можем это улучшить
И lock, и unlock используют транзакции Redis. Процесс lock можно упростить до следующего кода:
WATCH key
GET key # определить, истёк ли срок действия ключа
MULTI
SET key
EXPIRE key, expire_time + 1
Причина использования транзакций Redis (как я предполагаю), по-видимому, заключается в проверке истечения срока действия ключа перед его установкой.
Однако я считаю, что можно просто использовать команду SETEX, предоставляемую Redis, которая устанавливает ключ со временем истечения. Фактически, в документации Redis SETEX она приводится в качестве примера замены комбинации SET и EXPIRE на SETEX.
Вот аргументы в пользу замены:
- Установка значения в виде времени истечения и проверка этого перед установкой ключа излишни. Механизма TTL достаточно для обеспечения корректного истечения срока действия ключа.
- Даже если мы решим использовать время истечения в качестве значения, транзакция не требуется. Поскольку обеспечение атомарности между
GET(строка 2 в коде выше) иMULTI&EXECне даёт никаких преимуществ. Это связано с тем, что если блокировка не была захвачена, система просто повторит попытку.
Историческая справка
Я изучил историю коммитов в Git для получения дополнительной информации. Похоже, что когда блокировка Redis была внедрена, мы не использовали TTL, предоставляемый Redis. Функция TTL была добавлена значительно позже.
Поэтому я полагаю, что мы можем пойти ещё дальше и полностью отказаться от использования транзакций Redis.