Корректность распределенной системы ломается не только на явном отказе, но и на повторах, запаздывании данных и частично завершенных операциях.
Глава связывает модели консистентности, чтение своих записей, ключи идемпотентности, подавление дублей у обработчиков, безопасную публикацию событий и компенсации в паттерне Saga в одну рамку проектирования, где заранее определяется, какие инварианты можно ослабить, а какие нельзя терять ни при каких повторах.
На интервью по системному дизайну это особенно полезно: можно объяснять корректность через реальные механизмы защиты, а не прятаться за обещание обработки «ровно один раз», которое само по себе не описывает поведение системы при сбое.
Практическая польза главы
Модель консистентности
Заранее фиксируйте, где нужна строгая согласованность, где достаточно чтения своих записей, а где допустимо временное рассогласование.
Повторы без дублей
Проектируйте команды и обработчики так, чтобы повтор запроса или события не создавал новую бизнес-операцию.
Частичные сбои
Разбирайте потерю ответа, повторы, нарушение порядка и частично завершённые шаги как отдельные сценарии корректности.
Аргументация выбора
Объясняйте, какие инварианты вы сохраняете, чем платите за консистентность и как система сходится после сбоя.
Теория
Теорема CAP
Выбор модели консистентности всегда связан с доступностью, задержкой и ценой координации.
Консистентность данных и идемпотентность нужны не для идеального мира без сбоев, а для систем, где ответы теряются, события приходят повторно, а бизнес-операция завершается по частям. Главный вопрос главы: какой уровень согласованности действительно нужен и как сделать так, чтобы повтор команды не создавал новую бизнес-операцию.
Связанная глава
Jepsen и модели консистентности
Практический взгляд на то, как распределённые базы данных ведут себя под сбоями в реальности.
Модели консистентности
определяет, когда разные копии данных обязаны видеть одно и то же состояние. Рядом с ней почти всегда стоят , , , и . Когда архитектура допускает повторы, важно отдельно продумать , , , , , и .
Строгая консистентность
Платежи, денежные остатки, критичные инварианты и операции с высокой ценой ошибки.
Приходится платить более высокой задержкой, более дорогой координацией и более жёстким поведением при сетевых разделениях.
Чтение своих записей и сеансовая консистентность
Личные кабинеты, настройки профиля и другие сценарии, где пользователь должен сразу видеть свой результат.
Нужны закрепление чтения за правильным контуром, аккуратная работа с кэшем и явная политика свежести данных.
Согласование со временем
Каталоги, рекомендации, аналитические витрины и асинхронные интеграции между сервисами.
Нужно заранее определить, как продукт переживает временное рассогласование, лаги синхронизации и повторные события.
Паттерны идемпотентности
Активный паттерн
Ключ идемпотентности для синхронного API
POST-команды: платежи, создание заказа, выпуск счёта, запуск долгого процесса.
Как реализовать
- Клиент передаёт ключ идемпотентности в заголовке запроса, а сервер сохраняет этот ключ, отпечаток запроса и итоговый ответ.
- Если тот же ключ приходит повторно с тем же содержимым запроса, сервер возвращает уже известный результат, а не создаёт новую операцию.
- Срок жизни ключа выбирают по бизнес-риску: для финансовых операций это часто 24-72 часа, для коротких команд окно обычно меньше.
Риск: Если разрешить повторное использование того же ключа для другого содержимого запроса, конфликт спрячется под видом безопасного повтора.
Что идемпотентность не решает сама по себе
- Идемпотентность защищает от повторной доставки, но не заменяет контроль конкурентности и защиту бизнес-инвариантов.
- Для критичных команд полезно хранить не только факт обработки, но и итоговый ответ или код отказа, чтобы повтор был детерминированным.
- Нужно мониторить долю повторов, число отклонённых дублей и время разбора конфликтов по ключу идемпотентности.
Проверка
Тестирование распределённых систем
Идемпотентность нужно подтверждать тестами на повторы, нарушение порядка событий и частичные сбои.
Практические сценарии
Платёжный API
Повтор платёжного запроса после тайм-аута без идемпотентного контракта часто превращается в двойное списание.
Сбойный путь
Клиент
тайм-аут и повтор
Платёжный API
без ключа идемпотентности
База данных
дубль списания
Пользователь
двойное списание
Устойчивый путь
Клиент
ключ идемпотентности
API
проверка дубля и уникальности
Реестр
одна транзакция
API
возврат прежнего ответа
Что происходит
- Ключ идемпотентности связывает все повторы одного намерения клиента в одну бизнес-операцию.
- Даже если запрос приходит повторно, сервер возвращает прежний результат вместо новой транзакции.
- Уникальное ограничение и отдельная ручка статуса закрывают состояние гонки между несколькими повторами.
Риск: Срок жизни ключа и область его действия должны совпадать с реальным бизнес-окном операции.
Сценарий должен оставаться корректным при повторах, повторной доставке и нарушении порядка событий.
Практический чеклист
Для каждой критичной команды явно определено, что система делает при повторном запросе.
У событий есть устойчивый идентификатор и понятная стратегия подавления дублей у обработчика.
Выбранная модель консистентности зафиксирована в API-контракте и в ожиданиях продукта.
Есть фоновые процессы сверки, которые находят и исправляют рассогласования.
Команда тестирует повторы, повторную доставку и нарушение порядка событий в интеграционных сценариях.
Частая ошибка: считать, что платформа сама обеспечит обработку ровно один раз, и не делать операцию идемпотентной.
Источники
Связанные главы
- Теорема CAP - Почему при сетевых разделениях нельзя одновременно максимизировать консистентность и доступность.
- Теорема PACELC - Как компромисс между задержкой и консистентностью проявляется даже тогда, когда аварии нет.
- Event-Driven Architecture - Где повторы, частичные сбои и согласование состояния становятся повседневной инженерной задачей.
- Паттерны отказоустойчивости - Почему повторные попытки безопасны только там, где контракт уже спроектирован как идемпотентный.
- Тестирование распределённых систем - Как проверять повторы, нарушение порядка событий и частично завершённые операции до выхода в продакшен.
