MULTI/EXEC

Тема дорожной карты · Redis

MULTI открывает блок транзакции Redis, ставя последующие команды в очередь до тех пор, пока EXEC не выполнит все их атомарно по порядку. В блоке MULTI/EXEC команды возвращают QUEUED вместо обычных ответов; после EXEC Redis отвечает массивом результатов каждой команды. DISCARD отменяет поставленную в очередь транзакцию и выходит из блока MULTI. В отличие от транзакций баз данных, транзакции Redis не поддерживают откат — если одна команда в блоке завершается с ошибкой, остальные продолжают выполняться. Для условных транзакций (оптимистичная блокировка) WATCH key [key ...] отслеживает ключи до MULTI; если любой из наблюдаемых ключей изменяется до EXEC, вся транзакция прерывается и EXEC возвращает nil, позволяя клиенту повторить попытку.

Как это работает

MULTI/EXEC имеет два инструмента атомарности. MULTI/EXEC ставит команды в очередь; они выполняются как один блок — но нет rollback (Redis не ACID-D, изоляции тоже нет, если читаете между командами). WATCH добавляет optimistic locking — EXEC валится, если watched-ключ изменился. EVAL / EVALSHA исполняет Lua-скрипты атомарно на сервере; скрипт — одна неделимая операция. Lua — правильный инструмент для compound read+write, которые должны быть атомарными.

Когда применять

MULTI/EXEC — для "выполнить эти N команд как единицу без других команд между". WATCH + MULTI/EXEC — для compare-and-swap. Lua (EVAL) — для сложной атомарной логики (rate limiter, debounce, distributed semaphore). Всегда кешируйте SHA (EVALSHA) вместо повторной отправки тела скрипта — экономит bandwidth и парсинг.

Типичные ошибки

Ловушки MULTI/EXEC: расчёт, что MULTI/EXEC — транзакция в SQL-смысле (нет — без rollback); долгие Lua-скрипты блокируют однопоточный сервер (всё ждёт EXEC); не обрабатывают nil от EXEC (WATCH-конфликт — retry); Lua-код, мутирующий ключ на основе текущего значения без WATCH (race condition при разделении на команды).

Связанные понятия

Полезные ресурсы