Согласованность и транзакции
Пока все данные лежат в одной базе, корректность бесплатна — БД даёт ACID-транзакцию, и либо применяются все изменения, либо ни одного. Как только сервис разрезан на несколько процессов и баз, эта гарантия исчезает на границе первого сетевого вызова. Списать деньги в одном сервисе и зарезервировать товар в другом одной транзакцией БД уже нельзя — между ними сеть, которая теряет пакеты, тормозит и рвётся. Корректность распределённых данных приходится проектировать явно.
Главная ловушка темы — переносить интуицию однобазовой транзакции на распределённый мир. Теорема CAP говорит, что во время сетевого раздела придётся выбрать между согласованностью и доступностью — обещать обе сразу нельзя. Строгая согласованность стоит задержки и доступности, eventual-согласованность их покупает ценой временного расхождения реплик. Двухфазный коммит даёт атомарность, но блокирует участников и виснет при падении координатора. Прикладные паттерны — TCC и SAGA — отказываются от глобального лока в пользу резерваций и компенсаций, но требуют идемпотентности на каждом шаге. Тема разбирает этот спектр от теории CAP до конкретных протоколов распределённой транзакции.
Карта темы
- Теорема CAP — во время сетевого раздела система выбирает между согласованностью и доступностью (CP или AP), а не «два из трёх» в спокойном режиме.
- Модели согласованности — спектр от строгой (linearizable) до eventual, с промежуточными read-your-writes и monotonic reads, и размен задержки на доступность.
- Двухфазный коммит — координатор собирает голоса через PREPARE и коммитит только при единогласном «да», но блокирует участников и виснет при своём падении.
- Трёхфазный коммит — добавляет фазу PRE-COMMIT, чтобы участники могли решить без координатора, ценой лишнего round trip и допущения синхронной сети.
- Паттерн TCC — прикладная распределённая транзакция try-confirm-cancel: резерв ресурса, затем подтверждение или отмена на всех сервисах, с идемпотентностью.
- Паттерн SAGA — длинная транзакция как цепочка локальных шагов, каждый с компенсацией для отката, без глобальных локов и с eventual-согласованностью.
Частые ошибки и ловушки
| Ошибка | Последствие |
|---|---|
| Обещать согласованность и доступность одновременно | CAP запрещает это во время раздела — выбор C-vs-A не сделан, поведение под сбой непредсказуемо |
| Читать CAP как «выбери два свойства из трёх» в обычном режиме | Подменяется суть: выбор стоит только во время раздела, а не в стационаре |
| Считать строгую согласованность бесплатной | Linearizable-чтение платит задержкой и доступностью на каждой операции |
| Тянуть 2PC по сети между сервисами | Участники держат блокировки и виснут, если координатор упал после PREPARE |
| Мерить латентность 2PC по среднему узлу | Хвостовая задержка коммита — это самый медленный участник, а не средний |
| Реализовать TCC без идемпотентных try/confirm/cancel | Ретрай повторно резервирует или дважды списывает один и тот же ресурс |
| Не хранить состояние резервации в TCC и SAGA | После рестарта неясно, что подтверждать и что компенсировать |
| Считать, что SAGA даёт атомарность как БД-транзакция | SAGA даёт лишь eventual-согласованность через компенсации, без изоляции |
| Писать компенсацию SAGA неидемпотентной | Повторный откат портит данные или откатывает чужой шаг |
Значение для собеседований
Согласованность и распределённые транзакции — обязательная часть system design на senior-уровне Go-интервью, и проверяют не заучивание букв CAP, а понимаете ли вы, какой компромисс выбираете осознанно и чем за него платите. Интервьюер смотрит, отличаете ли вы поведение под сетевым разделом от спокойного режима, видите ли цену строгой согласованности и знаете ли, почему 2PC через сеть опасен, а прикладные паттерны вроде TCC и SAGA выживают за счёт компенсаций и идемпотентности.
Что обычно проверяют:
- Что на самом деле утверждает CAP — выбор C или A только во время раздела, а не «два из трёх» в стационаре.
- Чем строгая согласованность отличается от eventual и какие модели лежат между ними (read-your-writes, monotonic reads).
- Как работает 2PC и почему он блокирующий — что происходит с участниками, если координатор упал после PREPARE.
- Зачем 3PC добавляет PRE-COMMIT и почему его почти не используют на практике.
- Как устроен TCC (try-confirm-cancel) и почему каждый шаг обязан быть идемпотентным.
- Что такое SAGA, чем отличается оркестрация от хореографии и как работают компенсации при сбое посреди цепочки.
Типичный неверный ответ: «возьмём распределённую транзакцию, и всё будет атомарно, как в обычной базе». Это запускает разбор того, что атомарности через сеть не бывает бесплатно: 2PC блокирует и виснет, а TCC и SAGA дают лишь eventual-согласованность ценой компенсаций, которые сами должны быть идемпотентными, иначе ретрай при ненадёжной доставке (см. outbox и гарантии доставки) повторно применит уже выполненный шаг.