一、出现分布式事务的原因:
- 只跨库:单体的读写分离。注:库不仅仅指的db,还有cache
- 只跨服务:服务拆分库未拆分,由于不同服务开启不同的的数据库链接
- 跨库跨服务:即跨库又跨服务
二、分布式事务分类:
刚性分布式事务:强一致性(cp)
- xa、2pc、3pc
柔性分布式事务(使用多):最终一致性(ap,补偿/通知)
- 补偿性事务:TCC、saga。通过补偿性方法,使得数据恢复,属于同步事务
- 通知性事务:事务消息、最大努力通知事务。通过第三方(MQ)通知事务下游,属于异步事务
三、六大事务模型:
刚性事务模型:xa,2pc(两阶段提交又称2PC(two-phase commit protocol))
柔性事务模型:补偿类2(TCC、saga),通知类2(事务消息、最大努力通知事务)
注:saga与事务通知重点介绍
四、刚性分布式事务:
提到刚性分布式事务,首先想到的是2pc,在2pc之前首先应了解XA模型,刚性事务满足传统事务的ACID(ACID介绍: 传送门)
柔性事务对ACID的CI进行了取舍,刚性分布式事务由于性能差,在实际应用中使用很少,除非是对事务要求极为苛刻的金融公司,如蚂蚁金服大量使用2pc
五、XA模型(只是标准,无具体实现):
XA模型仅仅是定义了规范,使用的时候需要各个厂自己实现。目前XA具有很大性能问题,几乎没人用。 且只能用XA事务连接池,不能用jdbc
1.XA由AP、RM、TM组成:
六、2PC(XA模型的实现 two-phase commit protocol):
基于xa模式的2pc实现时序图:
两阶段提交2PC是XA模型的实现,AP发起commit请求,TM发起prepare投票,RM进行串行投票,都同意后,TM再commit,如果commit过程出现宕机等异常,节点服务重启后,根据XA recover再次进行commit补偿。
缺点(响应延时高、并发低):
- 同步阻塞模型
- 数据库资源锁锁定时间过程
- 全局锁(隔离级别串行化),并发低
- 不适合长事务场景,长事务(即事务多)
七、3PC(there-phase commit protocol):
- 为进行改进2pc,3pc1981提出,1982年确认理论方法,2pc是1978年提出,距今已经近50。
3pc是2pc的优化,不是严格的XA规范,解决脑裂引起的事务状态不确定问题,引入了超时和对齐(根据上次的结果,默认执行)的概念。如TM约定,5秒后提交事务,等待5秒,然后提交事务,如果存在未收到状态的RM,默认对齐。sql层面是,01解析sql,02记undo/redo,03提交事务。3pc比2pc多引入一个阶段,仅仅解决的是2pc因脑裂带来的事务状态丢失的问题(这是小缺陷),对于2pc的大缺陷(同步、并发低)一个也没解决,2pc还有很少的人用,3pc几乎根本没人用。
八、柔性分布式事务:
刚性分布式事务由于性能差(高延时、低吞吐量),在实际应用中使用很少,除非是对事务要求极为苛刻的金融公司,如蚂蚁金服大量使用2pc,在互联网高并发的要求下,2pc这类的刚性分布式事务根本无法满足我们的需求,因此出现的如TCC、saga类的柔性分布式事务。刚性事务在业内估计占有10%-20%
柔性分布式事务是对XA的妥协,降低对一致性的要求,从而降低数据库资源(RM)的锁定时间,提高性能。cap选取ap柔性分布式事务,而柔性分布式事务的落地理论就是base理论。base理论传送门
九、TCC(try-confirm-cancel)模型:
理论神器、初学者天堂、实践废物,对业务侵入性很大。TCC07年提出,09年引入国内
- try:尝试执行业务、完成所有业务检查,预留必要的业务资源(冻结)
- confirm:真正的执行业务,不再做业务检查
- cancel:释放try阶段预留的资源
看着和xa的2pc一样,实际上不同2pc是数据库层面的,tcc的业务层面,对业务侵入性强
举例:A用户向B用户转账500块
可以看出存在中间柔性状态,最终达到一致性,对数据的一致性做了取舍,而且通过中间字段对数据隔离性做了取舍。满足base理论。
但操作一步变3步,字段一个变3个,使得业务变复杂,而且应用的场景很有限,很难落地。
tcc的问题: - 问题1:网络丢失,如果子服务A执行完,子服务B的TryY出现网络抖动,网络丢失,一段时间后服务A超时,子服务B将
空回滚
。可借鉴XA引入TM(记录xid、事务状态等信息) - 问题2:网络超时,如果子服务A执行完,子服务B的TryY出现网络超时,一段时间后服务A超时,子服务B将空回滚,然后B的TryY执行成功,会造成资源悬挂问题。所以姗姗来迟的请求要拒绝,
防悬挂
。可借鉴XA引入TM(记录xid、事务状态等信息) - 问题3:服务幂等,如果服务重试可能执行多次要做
服务幂等
,服务幂等是分布式系统的必备要求。
九、saga模型:
- 起源于1987年的论文《Sagas》
- saga模型把分布式事务拆分成多个本地事务,每个本地事务都有相应的执行模块与补偿模块。
- 当saga事务中某个本地事务出错时,可通过调用相关的补偿方法恢复之前的事务(当第n个本地事务出错,补偿前n-1本地事务,因为第n个自己会回滚),达到最终一致性。
tcc是三步,首先try如果失败就回滚;saga是两步,直接execute,正常就结束了,异常就调用补偿模块,补偿模块可能复用(巨大的优化);saga也是串行化的?saga的串行与xa模式的串行不一样,saga的每个本地事务执行后都会提交,xa模式每个本地事务执行后不会提交,而是挂起。
saga的隔离性:
- 业务层控制并发(分布式锁)
- 应用层加锁(分布式锁)
- 应用层预先冷冻资源(业务隔离(业务中间态),如转账a转b,不直接转,而是转给中间账户,成功的话中间账户再转给b,在金融行业中间账号很常见)
saga的补偿模块:
- 向后恢复:补偿所有与完成的事务,如果任何一个事务失败。(历史回溯,Aop实现)
- 向前恢复:重试失败的事务,直到每个子事务最终都会成功。(异步,预先配置好流程,工作流状态机实现)
saga的问题:
- 问题1:空补偿可借鉴XA引入TM(记录xid、事务状态等信息)
- 问题2:服务幂等
tcc与saga的cancal与补偿可以异步,fastfail
,三次补偿失败就上人工智能(人)
十、刚性分布式事务与柔性分布式事务比较:
十一、遇到分布式事务的解决思路与方案:
- 业务规避->控制成本
- 能否异步->事务消息(半消息)
- 能否柔性->saga
- 2pc
- tcc->业务一致性
十二、事务消息:
事务消息是柔性分布式事务,通知型
缺点:
- mq需要支持半消息与消费保证,mq还可能存在时序性问题
- 业务需要改造,可进行事务回查
- 消费端需要处理幂等问题
优化:引入本地事务消息表,可解决发送端的原子性问题。将消息插入本地表,定时任务投递mq
十三、同步场景实现分布式事务设计:
补偿方法不一定写,curd,c与d对立,直接由,只需要写u操作,且bas为数据处理层,不涉及业务,可以写通用的(如果标注了补偿方法,就走个性的补偿方法,没有标注的就走通用的补偿方法)
十四、更优雅的补偿方案——seata-AT模式:
seata-AT模式也是saga的一种实现:自动补偿:
写操作前,生成前置镜像
写操作
写操作前,生成后置镜像;如果补偿,对比前后镜像,进行补偿
十五、saga开源方案:
tcc也有开源方案,但是实现成本太大,不推荐使用,如seata tcc模式,bytetccservice comb
是华为的一套微服务解决方案,不是独立的模块,如果使用需要使用全套的微服务解决方案。使用的是saga aop实现
seata
是阿里的产品,支持AT、saga、tcc、xa模式,语言上支持java支持go;而且支持全局锁,解决事务隔离的问题
- AT->saga Aop
- TCC->TCC
- Saga->saga 状态机
- XA->2PC
seata的清铭(肖宇)为了制定标准,给saga对着干
Hmily
是个人产品