Блокировка в Redis с TTL не помешала двум воркерам списать деньги
Чтобы задачу списания выполнял только один воркер, перед началом берётся блокировка:
if redis.set(f"lock:charge:{order_id}", worker_id, nx=True, ex=30):
charge(order_id) # обычно 2 секунды
redis.delete(f"lock:charge:{order_id}")
Однажды charge у первого воркера завис на 40 секунд из-за медленного ответа банка. Второй воркер взял блокировку и тоже списал деньги. Первый потом удалил блокировку второго.
Какой вывод верный?
- Блокировка с TTL не гарантирует исключительность — нужна защита на стороне данных
- Достаточно увеличить TTL до пяти минут, и проблема исчезнет
- Нужно использовать SETNX вместо SET с параметром nx
- Redis нельзя использовать для блокировок, только PostgreSQL
