В БД
Решается транзакциями с подходящим уровнем изоляции или SELECT ... FOR UPDATE — блокировка строки до конца транзакции.
В кэше
Атомарные операции Redis (INCR, SETNX, Lua-скрипты) предотвращают гонку на уровне кэша.
Оптимистичная vs пессимистичная блокировка
- Оптимистичная — при записи проверяем, изменились ли данные с момента чтения (version number / CAS). Нет блокировок, но возможен retry
- Пессимистичная — блокируем ресурс при чтении, чтобы никто не изменил. Без retry, но снижает параллелизм