什么是Saga
Saga是分布式事务领域最有名气的解决方案之一,最初出现在1987年Hector Garcaa-Molrna & Kenneth Salem发表的论文SAGAS里。
Saga是由一系列的本地事务构成。每一个本地事务在更新完数据库之后,会发布一条消息或者一个事件来触发Saga中的下一个本地事务的执行。如果一个本地事务因为某些业务规则无法满足而失败,Saga会执行在这个失败的事务之前成功提交的所有事务的补偿操作。
Saga的实现有很多种方式,其中最流行的两种方式是:
- 基于事件的方式。这种方式没有协调中心,整个模式的工作方式就像舞蹈一样,各个舞蹈演员按照预先编排的动作和走位各自表演,最终形成一只舞蹈。处于当前Saga下的各个服务,会产生某类事件,或者监听其它服务产生的事件并决定是否需要针对监听到的事件做出响应。
- 基于命令的方式。这种方式的工作形式就像一只乐队,由一个指挥家(协调中心)来协调大家的工作。协调中心来告诉Saga的参与方应该执行哪一个本地事务。
案例
以电商下单未例子,用户下单涉及到
1.生成订单 (订单服务)
2.扣减库存(库存系统)
3.扣除积分(积分系统)
4.生成出库单(配送系统)
基于事件方式
处理流程
1.用户生成订单 订单状态为待确认,并发送一个事件deduction_stock_event
2.库存服务接收到deduction_stock_event 完成库存扣除并发送一个积分扣除事件deduction_score_event
3.积分服务收到deduction_score_event 完成积分扣除 并发送一个生成出库单的事件create_send_order_event
4.配送系统收到create_send_order_event 完成
订单服务可能会监听 配某些服务的完成事件,比如配送系统处理完成,发送一个完成事件,订单状态改为完成
某一个服务发送异常 则依次向上发送补偿事件
优点
简单且容易理解。各参与方相互之间无直接沟通,完全解耦。这种方式比较适合整个分布式事务只有2-4个步骤的情形。
缺点
这种方式如果涉及比较多的业务参与方,则比较容易失控。各业务参与方可随意监听对方的消息,以至于最后没人知道到底有哪些系统在监听哪些消息。更悲催的是,这个模式还可能产生环形监听,也就是两个业务方相互监听对方所产生的事件
基于命令模式
命令模式需要一个新的服务(OSO)做协调者
- 订单服务创建一笔新订单,将订单状态设置为"待处理",然后让Order Saga Orchestrator(OSO)开启创建订单事务。
- OSO发送一个"扣除库存命令"给库存服务,库存服务完成扣除并回复"扣除完成"消息。
- OSO发送一个"增加积分命令"给积分服务,积分服务完成积分增加,并回复"增加成功"消息。
- OSO发送一个"配送命令"给物流服务,配送服务生成配送单,并回复"成功"消息。
- OSO向订单服务发送"订单结束命令"给订单服务,订单服务将订单状态设置为"完成"。
OSO清楚一个订单处理Saga的具体流程,并在出现异常时向相关服务发送补偿命令来回滚整个分布式事务。
实现协调中心的一个比较好的方式是使用状态机(Sate Machine)。
如果出现异常如:
- 库存服务回复OSO一个"库存不足"消息。
- OSO意识到该分布式事务失败了,触发回滚流程:
- OSO向订单服务发送"将订单状态改为失败命令",订单服务将订单状态更新为"失败"。
优点
- 避免了业务方之间的环形依赖。
- 将分布式事务的管理交由协调中心管理,协调中心对整个逻辑非常清楚。
- 减少了业务参与方的复杂度。这些业务参与方不再需要监听不同的消息,只是需要响应命令并回复消息。
- 测试更容易(分布式事务逻辑存在于协调中心,而不是分散在各业务方)。
- 回滚也更容易。
缺点
一个可能的缺点就是需要维护协调中心,而这个协调中心并不属于任何业务方