概述
发件箱模式用单次数据库事务取代不可靠的双写。状态变更与事件一起提交,中继负责带重试地发布,正确性不再取决于提交时 broker 是否在线。
关键步骤
- 在与状态变更相同的事务中把事件写入发件箱表。
- 运行中继轮询未发布行,发布后标记已发送。
- 按计划删除或归档已发布行以限制表增长。
- 让消费者幂等,使崩溃后的重试不会重复生效。
验证
- 事件行与状态变更一起提交。
- 中继崩溃后重试不丢事件。
- 重复投递被消费者按事件 id 去重。
- 已发布行随时间被清理。
注意事项
- 发件箱提供至少一次投递而非恰好一次,消费者必须容忍重复。
- 轮询增加延迟与负载;变更数据捕获可替代轮询但增加运维复杂度。
适用范围
本条目围绕「用事务性发件箱发布事件」给出可复制的步骤、验证方式与常见问题,适合需要按此流程落地的工程团队。执行时请结合自身上下文调整命令与阈值,并在变更前后留存证据,便于后续复核与回滚。
BEGIN;
UPDATE orders SET status = 'shipped' WHERE id = $1;
INSERT INTO outbox (aggregate_id, type, payload)
VALUES ($1, 'order.shipped', $2);
COMMIT;