Распределённый лок в Redis снимается чужим владельцем
Лок на обработку заказа реализован так:
ok, _ := rdb.SetNX(ctx, "lock:order:"+id, "1", 30*time.Second).Result()
if !ok {
return ErrBusy
}
defer rdb.Del(ctx, "lock:order:"+id)
processOrder(ctx, id) // обычно 2 с, изредка — больше 30 с
В проде изредка встречаются два одновременно работающих обработчика одного заказа. Что нужно изменить в первую очередь?
- Просто увеличить TTL лока до часа — тогда он гарантированно не успеет истечь во время самой долгой обработки
- Перенести лок в PostgreSQL: корректную взаимную блокировку даёт только транзакционная БД, а Redis для этого непригоден
- Записывать в лок уникальный токен владельца и снимать его атомарно Lua-скриптом, сверив токен; долгую обработку сопровождать продлением TTL
- Убрать TTL совсем: лок должен сниматься только явным `Del` после обработки, тогда чужой владелец его не перехватит
