不能直接用composer require illuminate/events实现saga,因为它仅提供基础事件分发能力,缺乏saga必需的状态跟踪、补偿链维护、失败重试和幂等性保障;真实saga需自建协调器(如ordersaga)或集成dtm等专用协调器。

为什么不能直接用 composer require illuminate/events 就完事
这个命令确实能装上 Laravel 的事件系统,但它只提供基础的事件分发能力,不包含 Saga 所需的状态跟踪、补偿链维护、失败重试和幂等性保障。你拿到的是“喇叭”,不是“指挥台”。真实场景中,OrderSaga 类必须自己管理事务序列、执行上下文、补偿回调绑定,以及关键的 execute() 中断恢复逻辑——而这些在 illuminate/events 里完全不存在。
composer require dtm-client 是更现实的起点
DTM 是目前 PHP 生态中少有的、真正开箱支持 Saga 编排 + 补偿 + 重试 + 幂等的独立协调器。它不依赖 Laravel 框架,但可通过 Composer 集成到任何 PHP 项目中。安装后,你不再需要手写 addTransaction() 和反向遍历补偿数组的逻辑,而是用 DTM 提供的 Submit() 和 RegisterBranch() 显式定义正向/补偿动作。
- 每个分支必须返回唯一
branch_id,DTM 用它做幂等键 - 补偿操作必须是 HTTP 接口(非闭包),因为 DTM 协调器要跨进程调用
- 失败时 DTM 自动按注册顺序的逆序发起补偿请求,不依赖 PHP 进程存活
- 本地事务提交后,必须立刻调用
dtmcli.Saga().Submit(),否则状态不会持久化
消息驱动 ≠ 丢掉事务边界,AMQP 或 Kafka 只是传输层
很多人误以为用了 RabbitMQ 就算“消息驱动 Saga”,结果发现补偿没触发、重试丢失、状态不同步。根本原因是:消息队列本身不保证 Saga 流程的原子性推进。你必须在消费者端显式调用协调器接口,比如:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
if ($saga->execute() === false) {
$dtm->compensate($sagaId); // 不是发个「rollback」消息就完事
}
常见错误包括:
- 在消息消费回调里直接执行本地事务,却不记录
saga_id和当前步骤,导致补偿时无法定位上下文 - 把补偿逻辑写成异步消息投递,而没做幂等校验,造成库存重复恢复
- 用
php-amqplib手动 ack 消息,却在补偿失败后未 nack,导致消息丢失
补偿操作必须独立部署,且暴露为可重入 HTTP 接口
这是最容易被忽略的硬性约束。Saga 的补偿不是函数调用,而是服务间契约。比如扣减库存失败后,恢复库存的 /api/v1/inventory/compensate 必须满足:
- 接收
saga_id和order_id作为路径参数或 body 字段 - 内部先查该
saga_id是否已执行过补偿(靠数据库唯一索引或 Redis SETNX) - 返回 200 表示成功,409 表示已补偿过,500 表示需重试 —— DTM 会根据状态码决定是否重试
- 不能依赖 session 或本地缓存,因为补偿可能由另一台机器发起
没有这个契约,再好的协调器也救不了你的数据一致性。










