Пишем на Python, создаём нейросети и ИИ-агентов.
Алгоритмы, задачи и вайбкодинг.
Личный блог автора - @just_genych
По вопросам рекламы или разработки: @g_abashkin
Post #2766
416
Паттерн Saga: распределённые транзакции без двухфазного коммита
Двухфазный коммит (2PC) в микросервисах приводит к блокировкам, единой точке отказа и проблемам с масштабированием. Saga заменяет его цепочкой локальных транзакций с компенсирующими действиями на каждый шаг.
Хореография против оркестрации
Хореография — сервисы сами общаются через события. Просто, но сложно трассировать цепочку. Оркестрация — выделенный координатор управляет шагами (через RabbitMQ, Kafka или HTTP). Для production выбирайте оркестрацию: она проще в отладке и масштабировании.
Типичная ошибка
Компенсации часто реализуют как простой rollback. Но в микросервисах отменить факт записи в базу без side-эффектов невозможно. Компенсация — это бизнес-логика, а не техническая отмена. Пример: отмена брони отеля должна послать запрос на освобождение номера, а не вызывать SQL rollback.
Production-пример и код
Рассмотрим бронирование отеля и авиабилета. Шаг 1 — бронь отеля, шаг 2 — билет. Если билет не прошёл, отменяем бронь отеля. Вот урезанный пример координатора:
Код не готов к production: нет идемпотентности, ретраев, durable storage. В реальном проекте состояние координатора хранят в PostgreSQL или Redis с сохраняемыми очередями.
Инженерные trade-offs
Saga — это eventual consistency. Какое-то время данные могут быть несогласованными. Если клиент прочитает частичный результат (например, отель забронирован, а билет нет), будет баг. Нужна либо read-side согласованность, либо флаг временного состояния.
Практический совет
Компенсации делайте идемпотентными на уровне бизнес-логики: два вызова отмены брони не должны создавать двойную запись. Для внешних API добавляйте timeout и fallback. Если компенсация упала, используйте dead letter queue и ручной джобу для доотмены.
Предупреждение
Главный подвох: компенсации тоже могут падать. Без retry и DLQ данные зависнут в неконсистентном состоянии. Не забывайте про мониторинг состояния Saga и алерты на долгие цепочки.
Вывод: Saga — это практичный паттерн для микросервисов, требующий тщательной реализации компенсаций, идемпотентности и durable состояния координатора для избежания неконсистентности.
Двухфазный коммит (2PC) в микросервисах приводит к блокировкам, единой точке отказа и проблемам с масштабированием. Saga заменяет его цепочкой локальных транзакций с компенсирующими действиями на каждый шаг.
Хореография против оркестрации
Хореография — сервисы сами общаются через события. Просто, но сложно трассировать цепочку. Оркестрация — выделенный координатор управляет шагами (через RabbitMQ, Kafka или HTTP). Для production выбирайте оркестрацию: она проще в отладке и масштабировании.
Типичная ошибка
Компенсации часто реализуют как простой rollback. Но в микросервисах отменить факт записи в базу без side-эффектов невозможно. Компенсация — это бизнес-логика, а не техническая отмена. Пример: отмена брони отеля должна послать запрос на освобождение номера, а не вызывать SQL rollback.
Production-пример и код
Рассмотрим бронирование отеля и авиабилета. Шаг 1 — бронь отеля, шаг 2 — билет. Если билет не прошёл, отменяем бронь отеля. Вот урезанный пример координатора:
class SagaCoordinator:
def __init__(self, steps: list["Step"]):
self._steps = steps
self._executed: list["Step"] = []
async def run(self):
for step in self._steps:
try:
await step.action()
self._executed.append(step)
except Exception:
for executed in reversed(self._executed):
await executed.compensation()
raise
Код не готов к production: нет идемпотентности, ретраев, durable storage. В реальном проекте состояние координатора хранят в PostgreSQL или Redis с сохраняемыми очередями.
Инженерные trade-offs
Saga — это eventual consistency. Какое-то время данные могут быть несогласованными. Если клиент прочитает частичный результат (например, отель забронирован, а билет нет), будет баг. Нужна либо read-side согласованность, либо флаг временного состояния.
Практический совет
Компенсации делайте идемпотентными на уровне бизнес-логики: два вызова отмены брони не должны создавать двойную запись. Для внешних API добавляйте timeout и fallback. Если компенсация упала, используйте dead letter queue и ручной джобу для доотмены.
Предупреждение
Главный подвох: компенсации тоже могут падать. Без retry и DLQ данные зависнут в неконсистентном состоянии. Не забывайте про мониторинг состояния Saga и алерты на долгие цепочки.
Вывод: Saga — это практичный паттерн для микросервисов, требующий тщательной реализации компенсаций, идемпотентности и durable состояния координатора для избежания неконсистентности.







