1. 传统事务微服务架构下面临的挑战
在微服务的架构中,单个服务中的事务仍然可以使用ACID事务。
但是,如果跨多个服务的事务,数据库也跨多个,这样传统的事务就没法解决。
例如,一个下单操作createOrder()将跨越多个服务:
OrderService --> PaymentService --> InventoryService --> LogisticsService
像上述这种跨服务的操作必须使用Saga来维护数据的一致性,而不是传统的ACID事务。
什么是Saga?
Saga是一种消息驱动的本地事务序列。
Saga通过一系列本地事务来更新数据库,发布消息或事件来触发Saga里的下一个本地事务。如果一个本地事务由于违反了业务规则而失败,Saga执行一系列补偿事务以撤回被前面事务产生的更改。
Saga的弱点:
Saga的弱点在于值满足ACD(原子性,一致性和持久性),而缺乏了ACID中的隔离性。
因此,需要找到办法来防止或减少由于缺乏隔离性而导致的并发异常。
2. 补偿事务
Saga使用补偿事务来回滚所做出的改变。
每一个事务都有对应的补偿事务来进行撤销之前进行的操作。
T1, T2, ... Tn, Tn+1失败 --> Cn, Cn-1, ... C1
Saga按照正常事务的反向顺序来执行补偿事务。
在之前的下单的例子中:
OrderService(下单) --> PaymentService(支付) --> InventoryService(扣减库存) --> LogisticsService(发货)
步骤 | 服务 | 事务 | 补偿事务 |
---|---|---|---|
1 | OrderService | createOrder() 下单 | rejectOrder() 撤单 |
2 | PaymentService | pay() 支付 | refund() 退款 |
3 | InventoryService | deductInventory() 扣减库存 | revertInventory() 补还库存 |
4 | LogisticsService | deliverGoods() 发货 | rejectGoods() 退货 |
注意: 不是每个步骤都需要补偿事务,如果是只读的步骤就不需要补偿事务。
3. Saga的协调模式
在Saga模式中,一个本地事务完成了,Saga要协调下一个参与方执行本地事务;如果任何本地事务失败了,Saga必须以相反的顺序执行补偿事务。
Saga的协调逻辑分为两种类型:
协同式(Choreography)
把Saga的决策和执行顺序逻辑分布在Saga的每一个参与方中,它们通过交换事件的方式来进行沟通。编排式(Orchestration)
把Saga的决策和执行顺序逻辑集中在一个Saga编排器类中。
Saga编排器发出命令式消息给各个参与方,指示这些参与方服务完成具体的本地事务操作。