你再不知道分布式事务,我就真的生气了( 四 )


你再不知道分布式事务,我就真的生气了

文章插图
 
方案如下:
  • 发起方将通知发给 MQ 。
  • 接收通知方监听 MQ 消息 。
  • 接收通知方收到消息后,处理完业务,回应 ACK 。
  • 接收通知方若没有回应 ACK,则 MQ 会间隔 1min、5min、10min 等重复通知 。
  • 接受通知方可用消息校对接口,保证消息的一致性 。
转账业务实现流程图:
你再不知道分布式事务,我就真的生气了

文章插图
 
交互流程如下:
  • 用户请求转账系统进行转账 。
  • 转账系统完成转账,将转账结果发给 MQ 。
  • 企业网银系统监听 MQ,接收转账结果通知,如果接收不到消息,MQ 会重复发送通知 。接收到转账结果,更新转账状态 。
  • 企业网银系统也可以主动查询转账系统的转账结果查询接口,更新转账状态 。
Saga 事务
Saga 事务由普林斯顿大学的 Hector Garcia-Molina 和 Kenneth Salem 提出 。
其核心思想是将长事务拆分为多个本地短事务,由 Saga 事务协调器协调,如果正常结束那就正常完成,如果某个步骤失败,则根据相反顺序一次调用补偿操作 。
Saga 简介:
  • Saga = Long Live Transaction(LLT,长活事务) 。
  • LLT = T1 + T2 + T3 + ... + Ti(Ti 为本地短事务) 。
  • 每个本地事务 Ti 有对应的补偿 Ci 。
Saga 的执行顺序:
  • 正常情况:T1 T2 T3 ... Tn
  • 异常情况:T1 T2 T3 C3 C2 C1
Saga 两种恢复策略:
  • 向后恢复,如果任意本地子事务失败,补偿已完成的事务 。如异常情况的执行顺序 T1 T2 Ti Ci C2 C1 。
  • 向前恢复,即重试失败的事务,假设最后每个子事务都会成功 。执行顺序:T1,T2,...,Tj(失败),Tj(重试),...,Tn 。
举个例子,假设用户下订单,花 10 块钱购买了 10 多玫瑰,则有:
  • T1=下订单
  • T2=扣用户 10 块钱
  • T3=用户加 10 朵玫瑰
  • T4=库存减 10 朵玫瑰
  • C1=取消订单
  • C2=给用户加 10 块钱
  • C3=用户减 10 朵玫瑰
  • C4=库存加 10 朵玫瑰

你再不知道分布式事务,我就真的生气了

文章插图
 
假设事务执行到 T4 发生异常回滚,在 C4 的要把玫瑰给库存加回去的时候,发现用户的玫瑰都用掉了,这是 Saga 的一个缺点,由于事务之间没有隔离性导致的问题 。
可以通过以下方案解决这个问题:
  • 在应用层面加入逻辑锁的逻辑 。
  • Session层面隔离来保证串行化操作 。
  • 业务层面采用预先冻结资金的方式隔离此部分资金 。
  • 业务操作过程中通过及时读取当前状态的方式获取更新 。
参考与感谢:
  • 干货 | 一篇文章带你学习分布式事务
  • 再有人问你分布式事务,把这篇扔给他
  • 聊聊分布式事务,再说说解决方案
  • MySQL事务实现原理
  • 详细分析 MySQL 事务日志(redo log 和 undo log)
  • 《Saga 分布式事务解决?案与实践》
  • 分布式事务解决方案之最大努力通知

【你再不知道分布式事务,我就真的生气了】


推荐阅读