场景: (User Service)
更新用户操作包含更新用户基本属性和分配角色,由两个线程分别执行,当一个线程执行成功另一个执行失败时,需要回滚整个处理流程
解决方案:使用CQRS事件溯源回滚聚合根到指定状态
事件溯源(Event Source):
事件溯源能够保证对应用状态所有的改变被当作一系列的事件存储起来,我们不仅仅能查询这些事件,我们还能利用这些事件记录还原应用过去的状态,并作为自动调整状态以应对追溯性变化的基础.
逻辑分析:
更新用户无论是更新用户基本属性还是分配角色,我们期望是从上一次对这个聚合根实例状态的改变节点开始,
比如第一次创建一个UserAggregate实例 {name=zhngsan,phone=123,assignedRoleList=[r01,r02,r03]},后来更新了这个聚合根实例将assigedRoleList属性从[r01,r02,r03]更新为[r01,r04]此时UserAggregate变为{name=zhngsan,phone=123,assignedRoleList=[r01,04]},假如又要对这个聚合根实例更新,那么我们期望从上一次assigedRoleList属性为[r01,r04]这个节点开始更新.
怎样得到过去某个状态改变的聚合根实例?
我们尝试通过调用AXON load()方法得到一个UserAggregate,测试发现无论用这个方法名的任何重载方法得到的聚合根实例状态都为初始化状态,也就是该聚合根第一次被创建的状态,这与我们的期望不相符,于是想到既然事件溯源 '能利用这些事件记录还原应用过去的状态'
不妨从Event Source下手,通过查阅它的API发现AXON提供了EventStore组件,该组件提供一种机制从底层事件存储器打开事件流,至此我们有了新的方法通过EventStore组件获取DomainEventStream表示由聚合发布的历史事件流,然后加入逻辑判断从事件流中过滤出当前业务最关注的事件,最终结合初始化状态聚合根实例和事件还原得到过去发生这个事件的聚合根实例.
比如上面给出的例子(不考虑程序真实执行过程中所产生的所有事件)对UserAggregate聚合根的改变一共产生3个事件,
1.UserCreatedEvent {name=zhngsan,phone=123}
2.RoleAssignedEvent {assignedRoleList=[r01,r02,r03]}
3.RoleAssignedEvent {assignedRoleList=[r01,r04]},此时我们期望从上一次assigedRoleList属性为[r01,r04]这个节点开始更新,只需,
a.调用AXON load()方法得到一个初始化状态UserAggregate实例 {name=zhngsan,phone=123,assignedRoleList=[r01,r02,r03]},
b.调用AXON EventStore readEvent()方法获取事件流,并通过版本号和事件类型(RoleAssignedEvent.class)过滤得到上一次最新的分配角色事件RoleAssignedEvent {assignedRoleList=[r01,r04]},
c.更新a b两步共同的assignedRoleList属性得到上一次最新的分配角色UserAggregate聚合根实例 {name=zhngsan,phone=123} 2.RoleAssignedEvent {assignedRoleList=[r01,r04]}.
回到我们最开始的话题,怎样回滚整个处理过程?
通过对上面怎样获取过去某个状态改变的聚合根实例的了解,不难发现回滚整个处理过程只是一个体力活,最关键的问题已经得到解决,所以就不详细介绍了.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
2018-08-28 controller 允许跨域访问
2018-08-28 Sublime Text 3 安装+注册+汉化
2018-08-28 POI 3.17
2018-08-28 JDK8时间格式转换