Представьте, что вы пришли в театр. У вас одно пальто и один номерок. Вы подходите к гардеробу, протягиваете номерок, и в эту же секунду ваш друг (которому вы дали ксерокопию номерка) подбегает к другому окошку и тоже протягивает свой номерок.
Если гардеробщики работают неслаженно, они оба могут посмотреть на номерок, оба пойдут искать пальто, и один из них выдаст пальто вам, а второй - вашему другу. В итоге: одно пальто, один номерок, но два человека получили вещь.
В программировании это называется Состояние гонки (Race Condition).
Это ситуация, когда результат работы программы зависит от того, в каком порядке выполняются параллельные процессы. Если два запроса влетают в систему одновременно и работают с одними и теми же данными, они могут испортить эти данные.
Классический пример - списание средств с баланса:
Запрос А: "Сколько у Васи денег?" -> Сервер: "100 рублей".
Запрос Б: "Сколько у Васи денег?" -> Сервер: "100 рублей" (потому что А ещё не успел списать).
Запрос А: "Списать 100 рублей" -> Успех.
Запрос Б: "Списать 100 рублей" -> Успех (потому что проверка была сделана раньше).
Итог: Вася получил 200 рублей выплат, хотя имел только 100. У вас убытки.
Оба запроса действовали на основе устаревшей информации. Они не знали о существовании друг друга. Это и есть гонка - оба бегут к данным, и кто первый успел, тот и побеждает, часто ценой целостности системы.
API (особенно REST) обычно работает по протоколу HTTP. Он статический (stateless). Это значит, сервер обслужил запрос и забыл о нём.
Если приходит 10 запросов одновременно, сервер может запустить их обработку в 10 разных потоках (threads). Каждый поток читает баланс, думает "ок, денег хватает" и списывает. Они не знают о существовании друг друга. Это идеальная среда для гонок.
В высоконагруженных системах, где одновременно обрабатываются тысячи операций с кошельками, заказами, билетами или любыми другими ограниченными ресурсами, вероятность возникновения гонок резко возрастает. Даже если код написан правильно с точки зрения логики одного запроса, параллельное выполнение может сломать всю картину.
При разработке RK-CMS мы не раз сталкивались с последствиями race condition: дублирующиеся списания, некорректные остатки на складе, задвоенные заказы. Мы прекрасно понимаем, насколько коварной может быть эта проблема: она проявляется не всегда, а лишь при определённом стечении обстоятельств - например, под высокой нагрузкой или при пиковых нагрузках.
Именно поэтому мы относимся к защите от гонок как к обязательной части архитектуры, а не как к опциональной фиче. Мы знаем, как с этим бороться, и используем проверенные механизмы, которые не дают двум параллельным запросам испортить данные.