Как гарантировать откат передачи сообщения при падении одного микросервиса на пути передачи

«Как гарантировать откат передачи сообщения при падении одного микросервиса на пути передачи» — вопрос из категории Брокеры сообщений, который задают на 23% собеседований Golang Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Используйте паттерн Saga или Transactional Outbox. В Golang можно реализовать через:

  1. Транзакционность БД + Outbox:
func ProcessOrder(ctx context.Context, order Order) error {
    tx, _ := db.BeginTx(ctx, nil)
    defer tx.Rollback()

    // 1. Сохраняем заказ в БД
    if err := SaveOrder(tx, order); err != nil {
        return err
    }

    // 2. Сохраняем событие в outbox таблицу
    event := OutboxEvent{
        Type:    "OrderCreated",
        Payload: order,
    }
    if err := SaveOutboxEvent(tx, event); err != nil {
        return err
    }

    // 3. Коммитим транзакцию
    return tx.Commit()
}
  1. Компенсирующие транзакции (Saga):
  • Для каждого шага определяем компенсирующее действие
  • При ошибке выполняем цепочку компенсаций
  1. Идемпотентность обработчиков:
  • Повторная отправка не должна вызывать дублирование эффекта

Дополнительно можно использовать:

  • Периодическую проверку статуса (health checks)
  • Таймауты и retry-логику
  • Dead Letter Queue для проблемных сообщений