Короткий ответ
Для большинства мультисервисных операций в микросервисной архитектуре предпочтительнее Saga, так как она не требует долгих блокировок и синхронной доступности всех участников одновременно; 2PC/XA рассматривают только в узких случаях, когда участники — это базы данных под общим контролем и бизнес готов терпеть цену в доступности и масштабируемости.
Как это работает подробнее
Saga выполняет шаги последовательно, коммитя каждый локально и используя компенсации при сбое последующих шагов; 2PC синхронно блокирует ресурсы всех участников на время голосования координатора.
2PC даёт более простое концептуальное рассуждение об атомарности, но снижает доступность операции до доступности самого ненадёжного участника и плохо масштабируется; Saga масштабируется и переживает временную недоступность участников, но перекладывает сложность на явное проектирование и поддержку компенсаций, создавая временные окна неконсистентности. Критерий выбора — количество и природа участников, допустимость временной неконсистентности, и готовность команды поддерживать логику компенсаций и мониторинг зависших транзакций.
Пример кода
Saga-оркестратор хранит состояние шагов:
step1: payment.charge -> succeeded
step2: inventory.reserve -> failed
-> компенсация step1: payment.refund запускается автоматически оркестратором,
событие логируется для аудита и алертинга при неудаче компенсацииЧто использовать на практике
- Практика. 2PC плохо сочетается с сетевыми сбоями — при недоступности координатора или участника во время голосования ресурсы остаются заблокированными неопределённо долго; Saga допускает промежуточные eventually consistent состояния, но требует явного проектирования компенсаций, включая случаи их собственного сбоя.
Подводные камни
- Риск. Выбирать 2PC из желания «гарантировать строгую атомарность», не оценив доступность и устойчивость участников к блокировкам; реализовывать Saga без механизма восстановления зависших процессов после перезапуска оркестратора.