Гонка событий (Race Condition) Гонка событий — ситуация, при которой… — Системный Аналитик — TG.ME

🔽 Гонка событий (Race Condition)

Гонка событий — ситуация, при которой результат работы системы зависит от порядка выполнения операций
Если несколько процессов одновременно работают с одним состоянием, итог может быть непредсказуемым

Может возникать в:
🟢микросервисах
🟢распределённых системах
🟢очередях сообщений
🟢асинхронных API
🟢frontend-приложениях
🟢потоковой обработке данных

🍃Сложность гонки событий: проблема проявляется нестабильно
Система может работать корректно, а затем случайно выдать ошибку


Когда возникает


⚪️несколько процессов работают с одним состоянием ( одновременно читают и изменяют)
⚪️хотя бы один процесс изменяет данные
⚪️порядок выполнения не контролируется
⚪️нарушение порядка доставки (события отправляются в одном порядке, а доставляются — в другом)
⚪️отсутствие координации между сервисами (каждый сервис видит только локальное состояние)
⚪️deadlock (несколько транзакций блокируют друг друга)


Типичные признаки

➖«плавающие» баги
➖редкие ошибки
➖невозможность стабильно воспроизвести проблему
➖случайные дубли
➖потеря части данных
➖периодическая рассинхронизация

Причины

🍃сетевые задержки
🍃ретраи
🍃повторная доставка сообщений
🍃независимая работа сервисов
🍃параллельные консьюмеры
🍃различная скорость обработки

Гонка всегда связана с принципом:
❕корректность системы зависит от последовательности событий
Если изменение порядка приводит к разному результату — система подвержена гонке


Backend и микросервисы


Частый источник гонок — параллельные запросы к одному ресурсу

Например:
✨несколько сервисов обновляют один заказ
✨несколько обработчиков меняют баланс
✨несколько консьюмеров читают одну очередь


Базы данных

При использовании транзакций гонка не исчезает

Проблемы:
➖Lost Update (когда изменения одного процесса перезаписываются изменениями другого, и часть данных теряется)
➖dirty read (чтение данных, которые были изменены другой транзакцией, но ещё не зафиксированы )
➖ non-repeatable read (повторное чтение одной и той же записи внутри транзакции возвращает разные значения, потому что другая транзакция изменила данные)
➖перезапись изменений


Брокеры сообщений

Не гарантируют отсутствие гонок
Создают условия, при которых она возникает

Проблемы:
⚪️задвоенные события 🤩 дважды изменится состояние
⚪️доставка не по очереди 🤩 итоговое состояние зависит от порядка
⚪️повторная доставка🤩 перезапишется состояние
⚪️параллельные консьюмеры 🤩 если работают с одим ресурсом, то есть риски гонки


Распределенные системы


В распределённых системах гонка — нормальное состояние среды

Причины:
🟢eventual consistency (изменения не применяются на всех серверах мгновенно)
🟢независимые сервисы
🟢сетевые лаги
🟢разные каналы доставки
🟢репликация


Примеры

Микросервисы с общей БД


➖сервис заказов и сервис оплаты работают с одной таблицей
➖сервис оплаты меняет статус заказа
➖сервис заказов одновременно обновляет адрес доставки

Оба сервиса:
1. читают одну запись
2. меняют локальную копию
3. сохраняют объект полностью.
Последний UPDATE уничтожает изменения другого сервиса

Как решать

✨обновлять только нужные поля
✨использовать оптимистическую блокировку
✨отказаться от общей БД


Event-driven архитектура

Сервис публикует:
➖OrderCreated
➖OrderCancelled

Потребитель получает их в обратном порядке
Клиент сначала получает письмо: «Заказ отменён»
А затем: «Заказ успешно создан»

Как решать


✨партицирование по orderId
✨версионирование событий
✨occurredAt timestamp


📎 Материалы

1. Небезопасная многопоточность или Race Condition
2. Что такое состояние гонки
3. Почему стоит проверять приложения на устойчивость к race condition
4. Разница между Data Race и Race Condition

📚 Книги
1. Высоконагруженные приложения - Мартин Клеппман
2. Микросервисы. Паттерны разработки и рефакторинга - Крис Ричардсон
3. Шаблоны корпоративных приложений - Мартин Фаулер
4. Release it! Проектирование и дизайн ПО для тех, кому не всё равно - Майкл Нейгард

#проектирование

➿➿➿➿➿➿➿➿
🧑‍🎓 Больше полезного в базе знаний по системному анализу
1❤13🔥11👏1
May 29, 2026 9.3K 3 118