Короткий ответ
Saga — последовательность локальных транзакций в разных сервисах с компенсирующими действиями при сбое; 2PC — протокол, при котором координатор синхронно согласует и либо коммитит, либо откатывает транзакцию во всех участниках атомарно, блокируя ресурсы до завершения голосования.
Как это работает подробнее
В Saga каждый сервис коммитит свою часть немедленно и публикует событие о результате; при неудаче запускаются компенсации для уже выполненных шагов. В 2PC координатор спрашивает всех участников «готовы закоммитить?» и только при единогласном «да» даёт команду commit всем.
Пример кода
Схема
Saga для оформления заказа:
1. Order Service: создать заказ (status=pending)
2. Payment Service: списать деньги -> событие "payment.succeeded"/"payment.failed"
3. при payment.failed: Order Service выполняет компенсацию -> status=cancelled
4. при payment.succeeded: Inventory Service резервирует товар -> событие "inventory.reserved"/"failed"
5. при inventory.failed: Payment Service выполняет компенсацию -> возврат денегЧто использовать на практике
- Практика. Saga подходит для микросервисов с независимыми БД, не требует постоянных блокировок, но усложняет код компенсаций; 2PC даёт строгую атомарность, но требует постоянной доступности всех участников, что плохо масштабируется.
Подводные камни
- Риск. Пытаться применить 2PC через REST к внешним сервисам, не поддерживающим протокол; забывать, что компенсация в Saga — отдельная бизнес-операция, которая сама может не выполниться (нужен retry и мониторинг).