文章目录
- 分布式事务
- 2PC(二阶段提交协议)
- 执行流程
- 优缺点
- 3PC(三阶段提交协议)
- 执行流程
- 优缺点
- 本地消息表(异步确保)
分布式事务
分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于分布式系统的不同节点之上。
简言之,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。 本质上来说,分布式事务就是为了保证不同数据库的数据一致性。
2PC(二阶段提交协议)
在分布式系统中,每一个机器节点虽然都能够明确地知道自己在进行事务操作过程中的结果是成功或失败,但是却无法直接获取到其他分布式节点的操作结果(即无法同步结果,一致性无法保证)。
为了保证事务处理的 ACID
特性,就需要引入一个称为协调者的组件来统一调度所有分布式节点的执行逻辑,这些被调度的分布式节点则被称为参与者。协调者负责调度参与者的行为,基于这个思想,衍生出了二阶段提交和三阶段提交两种协议。
2PC(Two-Phase Commit): 即二阶段提交,是为了使基于分布式系统架构下的所有节点在进行事务处理过程中能够保持原子性和一致性而设计的一种算法。
执行流程
第一阶段的主要内容就是进行投票,来表明是否有继续执行事务的必要。
阶段一:提交事务请求(投票阶段)
- 事务询问: 协调者向所有参与者发出事务询问,询问是否可以执行事务操作,并等待各参与者的响应。
- 执行事务: 各个参与者节点执行事务操作,并将
undo
和redo
信息记入事务日志中。 - 各参与者向协调者反馈事务询问的响应: 如果参与者成功执行事务,则反馈
YES
响应;否则反馈NO
响应。 - 开启第二阶段: 协调者接收到所有参与者的
YES
响应后进入第二阶段。
在第二阶段中,会根据第一阶段参与者的反馈来决定是否能够提交事务,要么全都成功,要么全都失败。
阶段二:执行事务提交(执行阶段)
- 执行事务提交
- 发送提交请求: 协调者向所有参与者发起提交请求。
- 事务提交: 参与者在收到提交请求后,会正式执行事务提交操作。
- 反馈事务提交结果: 参与者在完成事务提交之后向协调者发送
ACK
消息。 - 完成事务: 协调者接收到所有参与者的
ACK
后完成事务。
- 中断事务(第一阶段协调者未收到所有参与者的 YES 响应)
- 发送回滚请求: 协调者向所有参与者发起回滚请求。
- 事务回滚: 参与者在收到回滚请求后,利用阶段一记录的
undo
信息来执行事务回滚操作。 - 反馈事务回滚结果: 参与者在完成事务回滚之后向协调者发送
ACK
消息。 - 中断事务: 协调者接收到所有参与者的
ACK
后完成事务中断。
优缺点
- 优点
- 原理简单
- 实现方便
- 缺点
- 同步阻塞: 在执行过程中,所有参与该事务操作的逻辑都会处于阻塞状态,也就是说各个参与者在等待其他参与者响应的过程中将无法执行其他操作。
- 单点问题: 在上述过程中,协调者起到了核心的调度作用。一旦协调者出现了问题,那么整个提交流程将无法运转,甚至如果在二阶段的提交流程中出现了问题,将导致其他参与者都处于锁定事务资源的状态中,无法完成事务。
- 数据不一致: 倘若在第二阶段的提交过程中,协调者向所有参与者发送提交请求,由于网络原因导致只有部分参与者收到了提交请求,此时就导致了只有接收到请求的参与者进行了事务提交,而产生数据不一致的问题。
- 过于保守: 二阶段提交协议没有设计容错机制,任意一个节点的失败都会导致整个事务的失败。
3PC(三阶段提交协议)
3PC(Three-Phase Commit): 即三阶段提交,为了解决二阶段的缺陷,其将二阶段提交协议的提交事务请求过程一分为二,形成了由 CanCommit
、PreCommit
、DoCommint
三个阶段组成的事务处理协议:
执行流程
阶段一:CanCommit
- 事务询问
- 各参与者向协调者反馈事务询问的响应
阶段二:PreCommit
-
执行事务预提交
- 发送预提交请求
- 事务预提交
- 各参与者向协调者反馈事务执行的结果
-
中断事务
- 发送中断请求
- 中断事务
阶段三:DoCommit
- 执行提交
- 发送提交请求
- 事务提交
- 反馈事务提交结果
- 完成事务
- 中断事务
- 发送中断请求
- 事务回滚
- 反馈事务回滚结果
- 中断事务
需要注意的是,在阶段三中可能会出现以下两种问题:
- 协调者出现问题(单点问题)
- 协调者和参与者之间的网络出现故障(网络拥塞)
无论出现上述那种问题,最终都会导致参与者无法及时的接收到来自协调者的 DoCommit
或是 Abort
请求,针对这种异常情况,参与者都会在等待超时后继续进行事务提交。
优缺点
- 优点: 相较于二阶段提交协议,降低了参与者的阻塞范围,并且能够在出现单点故障后继续达成一致。
- 缺点: 三阶段提交协议在去除阻塞的同时也引入了新的问题,那就是参与者在收到预提交的消息时,如果出现了网络分区的情况,协调者与参与者无法进行正常的网络通信,但是参与者依旧会进行事务的提交,从而导致数据的不一致。
本地消息表(异步确保)
本地消息表与业务数据表处于同一个数据库中,这样就能利用本地事务来保证在对这两个表的操作满足事务特性,并且使用了消息队列来保证最终一致性。
- 在分布式事务操作的一方完成写业务数据的操作之后向本地消息表发送一个消息,本地事务能保证这个消息一定会被写入本地消息表中。
- 之后将本地消息表中的消息转发到消息队列中,如果转发成功则将消息从本地消息表中删除,否则继续重新转发。
- 在分布式事务操作的另一方从消息队列中读取一个消息,并执行消息中的操作。
这里的消息队列不是单纯的数据结构,而应该看作由标志和操作两部分共同组成的中间件,用以标识某一操作是否成功,只有当左侧的分布式节点确实完成了某项操作,右侧的其他节点才有同步这项操作的必要。