分布式事物理解
分布式事物问题在分布式系统中是一个非常重要的问题,也是非常棘手不好处理问题,所以下面我们就将来理解一下什么是分布式事物,现在业界比较成熟的分布式解决方案都有那些……
什么是分布式事物
百度百科上是这样说的,分布式事物是指事物参数者,支持事物的服务器,资源服务器以及事物管理器分别位于不同的分布式系统的不同节点之上。
通俗的将就是一次大的操作有不同的若干小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事物需要保证这些小的操作要么全部成功,要么全部失败。其实就是为了保证不同数据库数据的一致性。
分布式事物产生的原因
大概有两个方面的原因:
数据库的分库分表
比如就拿转账来说,你给朋友转钱,你的账户信息数据在一个数据库上,你朋友的账户信息再另外一个库上,那么需要先扣减你账户上钱,然后给你朋友账户上添加钱。所以我们就需要要保证他们同时成功,才完成这笔转账操作。
应用的微服务化
现在一个大电商团队,系统架构是有多个服务拆分成不同服务来支持整个电商网站的运营,如订单服务,用户中心,库存服务,交易中心等等每个服务都有对应不同的db存储,这个时候用户下单就可能需要操作订单,库存,交易中心等多个服务操作,此时为了保证数据一致性,就需要使用到分布式事物
分布式事物的基础
事物的ACID特性
- 原子性
- 一致性
- 隔离性
- 持久性
但是这些ACID的四大特性,已经无法满足我们分布式事物,这个时候根据生产业务特定和分布式问题方案就产生一些新的理论
CAP理论
CAP理论也被叫做鲁尔定理,这个理论不光作为分布式事物解决参考,还作为分布式系统高可用设计的理论支持
C,Consistency一致性
A,Availability可用性
P,Partition tolerance分区容错性
三个方面不能同时满足,必须舍弃其一
那么舍弃策略就共有三种
CA:显然舍弃P,不允许分区,这是违背分布式系统设计的初衷的
CP:放弃高可用来达到数据强一致性
AP:要高可用就需要放弃一些一致性,一旦分区发生,节点之间可能会失去联系,为了高可用,每个节点只能用本地数据提供服务,这样会导致全局数据不一致性
从以上分析,其实在分布式系统中,我们取舍只能在C,A中进行取舍了。
BASE理论
Basically Available基本可用
分布式系统在出现故障时,允许损失部分可用功能,保证核心功能可用
Soft State 软状态
允许系统中存在中间状态,这个状态不影响系统可用性
Eventually Consistent 最终一致性
最终一致是经过一段时间内后,所有界定数据都会达到一致
BASE,它是通过牺牲强一致性来获得可用性,并允许数据在一段时间内是不一致的,但最终达到一致状态。
分布式事物的结局方案
基于XA协议的两阶段提交(2PC)
XA是一个分布式协议,XA中大致分为两个部分,事物管理器和本地资源管理器。
本地资源管理器往往有数据库实现
事物管理器作为全局的调度者,负责各个本地资源的提交和回滚
下面是一个2PC流程图
阶段一
1.事物询问
协调者向所有的参与者询问,是否准备好执行事务,并开始等待各个参与者的响应。
2.执行事务
各个参与者节点执行事务操作,并将undo和Redo信息计入事物日志中
3.各个参与者向协调者反馈事务询问的响应
如果参与者成功的执行了事物操作,那么就反馈给协调者Yes的响应,标示事物可以执行
如果没有成功执行事务,就返回No给协调者,表示事物不可以执行
阶段二
阶段二中会根据阶段一的投票结果执行2中操作:执行事务提交,中断事物
执行事务提交步骤如下:
1.发送提交请求,协调者想所有参与者发出commit请求
2.事物提交,参与者收到commit请求后,会正式执行事务提交操作,并在完成提交之后释放整个事物执行期间占用的资源
3.反馈事物提交结果,参与者在完成事务提交之后想事物协调者发送ACK
4.协调者接收到所有参与者的反馈ACK后信息,完成事务
中断事物步骤:
1.发送回滚请求,协调者向所有参与者发送Rollback请求
2.事物回滚:参与者接收到Rollback请求后,会利用一阶段记录的Undo信息来执行事务回滚操作,并在完成回滚之后释放事物执行期间所有资源
3.反馈事务回滚结果,参与者完成事物回滚之后,向协调者发送ACK请求
4.中断事物,协调者接收到所有参与者的反馈ACK信息后完成事务中断
优缺点:
优点:原理简单,方便实现
缺点:性能不理想,无法完成高并发场景
同步阻塞
协调者的单点问题
数据不一致
XA相关框架:
Atomikos TransactionsEssentials
是一个为java平台提供的开源事物管理器
消息事务+最终一致性
消息事务就是基于消息中间件的两阶段提交,本质上是对消息中间件的一种特殊利用,它是将本地事物和发消息放在一个分布式事物中,保证要么本地操作成功并且对外发消息成功,要么都失败,如阿里RocketMQ就是采用这种特性来支持分布式事物,
1.生产者发送事务消息到消息中间件booker,获取到该message的transactionId,状态就是半事物消息(此消息对消费者不可见)记录log,然后相应生产者返回
2.生产者收到消息中间件的响应后,执行本地事物
3.发送提交消息给消息通知中间件
4.消息中间件收到通知消息,修改消息的状态(此时消息对消费者可见)
大概流程是这样,但是这流程当中会有好多机制措施保证
问题:如何保证生产者执行完本地事物后,向mq发送消息保证mq成功收到呢? 比如
本地事物执行成功后宕机了,确认消息没有发出
确认消息发出,但是网络原因导致RocketMQ集群没有收到
确认消息发出。RocketMQ集群收到确认消息,但是生产者不知道确认消息发出是否成功
说明:在3.2.6之前版本有事物回查机制,之后搬去取消回查机制,采用新的措施。
关于RocketMQ中生产者如何保证确认信息发送到MQ集群策略会另开一篇博客详细说明
TCC
TCC(Try-Confirm-Cancel)概念
- Try阶段:尝试执行,完成所有业务操作检查(一致性),预留必须业务资源
- Confirm阶段:确认真正执行业务,不做任何业务检查,只使用Try阶段预留的业务资源,Confirm操作满足幂等性,必须要幂等设计,Confirm失败后需要进行重试
- Cancel阶段:取消执行,释放Try阶段预留的业务资源,Cancel操作满足幂等性,Cancel阶段的异常和Confirm阶段异常处理方案一直
例子资金的冻结解冻案例就是TCC方案的实施
try—>资金冻结
confirm—->资金扣除
Cancel—–>资金解冻
TCC的使用场景:
- 强隔离性,严格一致性要求操作业务
- 执行时间较短的业务
开源中间件:byte-tcc/tcc
https://github.com/liuyangming/ByteTCC/
总结
分布式事物,实际上就是对多个数据库的事物进行统一的控制,只是根据具体生产上使用场景不同产生了不同控制策略:如不是用分布式事物不控制,弱控制和完全控制。
1.不控制就是不引入分布式事物
2.弱控制就是一些变通的2PC方案,如RocketMQ的分布式事物方案,实现最终的一致性;好处是提高系统的处理性能和并发量,缺点是数据一致性减弱,实现最终一致性
3.完全控制就是严格实现两阶段提交,好处保障了一致性,但是牺牲了性能
所以方案没有好与坏,只有根据具体的业务场景选择合适的。技术永远是未业务服务的所以针对不同业务进行技术选型是架构师必备的技能。