Практическое задание
Распределённая блокировка для cron-скриптов
Ночные задачи запускаются по cron на нескольких серверах, и иногда одна и та же задача выполняется дважды одновременно. Напиши обёртку /usr/local/bin/with-lock (bash, исполняемый файл), которая берёт блокировку в Redis:
with-lock <name> <command...>
Требования:
- блокировка — ключ
lock:<name>, значение — уникальный токен этого запуска; ключ ставится одной атомарной командой, только если его ещё нет, и с TTL 30 секунд (чтобы упавший процесс не держал блокировку вечно); - если блокировка занята — сразу выйти с ненулевым кодом, команду не запускать и не ждать;
- иначе — выполнить команду и выйти с её кодом;
- после команды снять блокировку, только если токен в ключе всё ещё твой (за время работы TTL мог истечь, и блокировку взял другой процесс). Сравнение и удаление — атомарно, одним
EVAL(Lua-скрипт на сервере), а не паройGET+DEL.
Redis уже запущен на 127.0.0.1:6379.
- redis
- SET NX EX
- EVAL
- Lua
- распределённая блокировка
- bash