使用Axon Framework级联触发命令及查询触发命令的最优方案
Axon Framework 两个常见场景实现方案解答
问题1:命令执行成功后触发另一命令的最优实现
首先明确几个可选方案的适用性:
- 绝对不要在
@EventSourcingHandler中发起新命令:该类处理器的唯一作用是重构聚合状态,不管是首次创建聚合还是历史事件重放都会执行,在此处发命令会导致事件重放时重复发起命令,直接引发数据混乱。 - 普通
@EventHandler中发命令仅适用于极简单的无一致性要求的场景:这种方案需要自行处理事件重试导致的命令重复发送问题,且没有内置的补偿机制,一旦第二个命令执行失败没有统一的回滚链路,业务逻辑分散也不利于后续维护,非特殊情况不推荐。 - 最优方案是使用Saga实现:Saga是Axon原生提供的跨聚合、跨限界上下文流程协调组件,你只需要定义Saga类监听第一个聚合的
XXXCreatedEvent事件,在事件处理方法中通过CommandGateway发送第二个聚合的创建命令即可。
该方案的核心优势:- 自带幂等保证,Axon会确保同一个Saga实例对同一事件只会处理一次,避免重复发命令
- 内置状态管理,可直接定义第二个命令执行失败后的补偿逻辑,天然满足最终一致性要求
- 所有跨域流程逻辑收敛在Saga中,后续维护时可直观梳理完整业务链路
问题2:从查询中触发命令的最优实现
不推荐直接在查询处理类中发送命令,该做法直接打破了CQRS读写分离的职责边界,还会引发并发场景下重复触发创建命令的问题,可根据业务场景选择以下两种方案:
场景1:允许短时间最终一致性
如果业务允许查询首次返回默认结果,后续自动同步创建后的正确数据,可在查询侧判断记录不存在时,异步发送创建命令,无需等待命令执行完成直接返回默认值即可,该方案性能最高且完全符合CQRS设计原则。
场景2:要求创建完成后才返回结果
在上层应用服务层做逻辑编排,不要把逻辑耦合到查询处理器中:
- 应用服务先调用
QueryGateway发起查询 - 结果不存在时调用
CommandGateway发送创建命令,同步等待命令执行完成 - 再次发起查询拿到最新结果返回给调用方
最佳实践:该场景必须给创建命令加上业务唯一标识作为幂等键,命令侧做好幂等校验,避免并发请求导致重复创建问题。
如果创建逻辑完全没有业务规则校验、不需要触发任何后续流程,极端情况下也可以直接在查询侧存储层写入默认记录,该方案仅做备选,不推荐普遍使用,会跳过命令侧的所有业务校验逻辑,容易产生脏数据。
内容的提问来源于stack exchange,提问作者Alexandre
相关产品推荐
相关产品推荐

