@toc:
- 分布式事务 → 2PC、3PC协议
- 2PC协议实现;
- 3PC协议实现;
- 2PC & 3PC比较
分布式事务→ 2PC、3PC协议
- 事务的特性: ACID (👉🏻[[../32.Database/MySQL-03b-事务的特性和实现#ACID特性]])
- 分布式事务解决分布式数据的一致性(Consistency)问题
- 数据库系统保证一致性是「提供正确的增/删/改/查等语义」的基础, 分布式系统一致性问题来自于:
- 数据多副本存储(每个副本在不同物理机) 需要保证多副本数据一致性;
- 一个完整事务涉及多个数据库的多表(例如银行转账问题, a和b账户不在一个数据库)
- 解决分布式一致性的协议和算法: 2PC、3PC、Paxos
- 分布式事务对比分布式锁: 分布式锁是「多client抢占一个公共资源」, 分布式事务是「一个client操作多个资源, 并保证一致性」
相关阅读:
- 分布式系统一致性: 分布式系统-Consistency
- MySQL的ACID如何实现: [[../32.Database/MySQL-03b-事务的特性和实现]]
- Raft: Redis-03Raft实现
- Paxos: [[分布式系统-Consistency-Paxos]]
2PC
2PC(Two Phase Commitment Protocol, 2阶段提交协议)概述:
分布式事务中的角色:
- 协调者, 事务管理器(TM)
- 参与者, 资源管理器(RM), 在分布式事务中可能是多个数据库
执行步骤:
- 1)准备阶段:
- 事务协调者(事务管理器)给每个参与者(资源管理器)发送Prepare消息;
- 每个参与者(资源管理器)要么直接返回失败,要么写本地的redo和undo日志并返回成功;
- 2)提交阶段:
- 如果协调者(TM)收到了参与者(在第一阶段返回的)失败, 或者超时, 协调者(TM)发送 rollback 消息 给每个参与者;
- 如果协调者(TM)收到了每个参与者返回的成功消息, 协调者(TM)发送 commit 消息 给每个参与者;
- 参与者正式完成操作(commit 或 rollback), 释放事务期间占用资源, 并向协调者发布完成消息;
- 协调者(TM)收到所有参与者的完成消息, 最终完成事务
2PC的问题:
- 协调者故障: 每个参与者的状态没有超时机制, 在第二阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,这种状态一直阻塞下去;
- 数据不一致: 当协调者(TM)向参与者(RM)发送commit请求之后,发生了局部网络异常或者在发送commit请求过程中协调者发生了故障,这回导致只有一部分参与者接受到了commit请求。
- 二阶段无法解决的问题:协调者再发出commit消息之后宕机,而唯一接收到这条消息的参与者同时也宕机了。那么即使协调者通过选举协议产生了新的协调者,这条事务的状态也是不确定的,没人知道事务是否被已经提交。
3PC
3PC协议概述:
步骤:
- 1)CanCommit:
- 协调者(TM)向参与者发送 CanCommit请求。询问是否可以执行事务提交操作。然后开始等待参与者的响应。
- 参与者(RM)接到 CanCommit请求之后,正常情况下,如果其自身认为可以顺利执行事务,则返回Yes响应,并进入预备状态。否则反馈No
- 2)PreCommit:
- 协调者TM 向参与者发送 PreCommit请求;
- 参与者RM 接收到 PreCommit请求后,会执行事务操作,并将undo和redo信息记录到事务日志中。并向协调者返回成功;
- 协调者TM 未收到某个参与者的确认请求,或者有参与者超时未返回, 协调者向所有参与者发送 abort
- 3)DoCommit:
- 协调者(TM)收到了所有参与者的确认请求,且没有参与者超时未返回,协调者向所有参与者发送doCommit请求;
- 参与者接收到 doCommit请求之后, 执行正式的事务提交. 完成后向协调者发送响应
- 协调者(TM)接收到所有参与者的确认响应之后,完成事务
- 协调者(TM)未收到某个参与者的确认请求,或者有参与者超时未返回, 协调者向所有参与者发送abort
- 在这一阶段, 如果参与者(RM)无法及时接收到来自协调者(TM)的 doCommit或者 rebort请求时, 会在等待超时之后,会继续进行事务的提交。
可能出现的问题:
参与者(RM)无法及时收到来自协调者(TM)的信息之后,会默认执行commit。而不会一直持有事务资源并处于阻塞状态。但是这种机制也会导致数据一致性问题,因为,由于网络原因,协调者发送的abort响应没有及时被参与者接收到,那么参与者在等待超时之后执行了commit操作。这样就和其他接到abort命令并执行回滚的参与者之间存在数据不一致的情况。
➤ 2PC & 3PC 比较:
- 2PC: 协调者只在 Prepare阶段可能发送 rollback指令,
3PC: 协调者在 preCommit 和 doCommit阶段, 都会根据参与者返回决定是否发生abord指令
3PC: 在参与者收到 preCommit指令后, 如果等待协调者超时, 参与者会自动提交commit
- 2PC: 在参与者收到 Prepare 指令后, 如果等待协调者超时, 参与者会一直等待下去(阻塞)
@ref: