共计 1584 个字符,预计需要花费 4 分钟才能阅读完成。
事务的概念
事务:事务是由一组操作构成的可靠的独立的工作单元,具备ACID的特性,并由类似begin transaction和end transaction语句或者函数界定。
ACID特性:原子性,一致性,隔离性,持久性
- 原子性(atomicity):一个事务为不可分割的工作单位,要么都做,要么都不做
- 一致性(consistency):事务必须是使数据库从一个一致性状态变成另一个一致性状态。
- 隔离性(isolation):一个事务的执行不能被其他事务干扰。
- 持久性(durability):一个事务一旦提交,它对数据库中数据的改变就是永久性的。
分布式事务
- 基于XA协议的两段式提交(2pc)
- 三段式提交(3pc)
- Try Confirm Cancel(TCC)
- MQ事务消息(可靠事件模式)
- MQ非事务消息(加独立消息服务/本地事务表)
- 柔性事务(最大努力通知/补偿)
- Sagas(长事务)
下面介绍其中的几种
基于XA协议的两段式提交(2pc)
在分布式系统中,每个节点可以知道自己的操作是否成功或失败,但是无法知道其他节点的操作的成功或失败。当一个事务跨多个服务时,需要引入一个协调者组件来掌控所有节点(参与者)的操作结果,并将最终指示这些节点是否进行真正的提交。
工作流程
1)第一阶段
- 协调者会问参与者节点是否可以进行提交操作
- 各个参与者开始执行事务前的准备工作:资源上锁,预留资源等
- 各个参与者回应协调者,如果事务准备工作成功,就回应“可以提交”,否则回应“拒绝提交”
2)第二阶段
- 如果所有参与者回应“可以提交”,那么协调者向所有参与者发布“正式提交”的命令。参与者完成正式提交,并释放所有资源,回应“完成”,协调者收集所有“完成”回应后并结束这次全局事务
- 如果有一个或多个参与者回应“拒绝提交”,那么,协调者向所有参与者发送“回滚操作”,并释放所有资源,并回应“回滚完成”,协调者收集各参与者的回应后,取消全局事务
缺陷
- 同步阻塞:参与节点是事务阻塞型的,事务过程中公共资源得不到释放,并发上不去
- 单点故障:协调者发生故障,在未选举出新的协调者之前,参与者会一直阻塞下去
- 网络抖动导致脑裂现象(过半机制就是为了防止脑裂问题),导致事务参与者不能很好的执行协调者的指令,出现数据不一致的现象
- 二阶段无法解决的问题:协调者再发出commit消息后宕机,参与者收到消息后也宕机,就算再选举出新的协调者,也无法知道这个参与者的事务状态是否提交
三段式提交(3pc)
相比2pc的区别
- 引入了超时机制,同时在参与者和协调者中引入超时机制
- 在第一阶段和第二阶段插入一个准备阶段,就是将2pc的准备阶段再一分为二,形成cancommit,precommit,docommit三个阶段,就不详细介绍
MQ事务消息(可靠事件模式)
在常见的消息中间里RocketMQ是支持事务消息的,类似采用的二阶段提交,而RabbitMQ和kafka是不支持的。
实现思路
- 发送一条消息,rocketMQ将这条消息标记为Prepared,此时这条消息消费者是无法消费到的
- 执行业务逻辑代码,可能是一个本地数据库事务操作
- 确认发送消息,这个时候,RocketMQ将这条消息标记为可消费
- 如果确认发送失败,RocketMQ会定期扫描集群中的Prepared消息,然后按照事先配置好的策略,进行回滚或者发送确认消息
优点:实现了最终的一致性,不需要依赖本地数据库事务
缺点:实现难度大,且不通用,其他MQ不支持
MQ非事务消息(加独立消息服务/本地事务表)
生产发消息到一个独立的消息服务或本地事务表中
思路
- 生产者将消息发送到一个自己写的独立服务中,处于prepare状态
- 业务逻辑处理成功后,确认发送消息,才会将消息发送到消息队列中
- consumer处理好消息后,返回ack给消息队列和独立消息服务,独立消息服务把这条消息删除,定时扫描prepare的消息,向producer确认是否发送
正文完