← 中文资源

简体中文版本

用事务性发件箱发布事件

把事件与状态变更写入同一事务,再异步中继并重试,配合幂等消费者,保证至少一次发布。

阅读英文原文

概述

发件箱模式用单次数据库事务取代不可靠的双写。状态变更与事件一起提交,中继负责带重试地发布,正确性不再取决于提交时 broker 是否在线。

关键步骤

  1. 在与状态变更相同的事务中把事件写入发件箱表。
  2. 运行中继轮询未发布行,发布后标记已发送。
  3. 按计划删除或归档已发布行以限制表增长。
  4. 让消费者幂等,使崩溃后的重试不会重复生效。

验证

  • 事件行与状态变更一起提交。
  • 中继崩溃后重试不丢事件。
  • 重复投递被消费者按事件 id 去重。
  • 已发布行随时间被清理。

注意事项

  • 发件箱提供至少一次投递而非恰好一次,消费者必须容忍重复。
  • 轮询增加延迟与负载;变更数据捕获可替代轮询但增加运维复杂度。

适用范围

本条目围绕「用事务性发件箱发布事件」给出可复制的步骤、验证方式与常见问题,适合需要按此流程落地的工程团队。执行时请结合自身上下文调整命令与阈值,并在变更前后留存证据,便于后续复核与回滚。

BEGIN;
  UPDATE orders SET status = 'shipped' WHERE id = $1;
  INSERT INTO outbox (aggregate_id, type, payload)
  VALUES ($1, 'order.shipped', $2);
COMMIT;