分布式学习五:二阶段提交协议(2PC)
前言
在分布式系统中,每个节点都知道自己在事务操作的结果是成功还是失败的,却无法直接获取其他分布式节点的事务结果
因此,当一个事务操作需要跨节点时,为了保证事务的ACID特性,就需要引入"协调者(Coordinator)" 的组件来统一调度所有分布式节点的事务处理逻辑,这些被调度的节点称为"参与者(Participant)"
协调者负责调度参与者的行为,并最终决定这些参与者是否要把事务真正的提交 (完成事务)
或者决定这些参与者将事务全部回滚 (回滚事务)
基于这个思想,衍生出了二阶段提交和三阶段提交两种协议
二阶段提交(two-phase commit)
将事务的提交过程分成了2个阶段来处理,其执行流程如下:
阶段一:提交事务请求
1:事务询问:协调者向所有参与者发送事务内容,询问是否可以开始提交事务操作,并等待参与者的响应
2:事务执行:参与者接收到提交事务请求,各个参与者执行事务操作,并将undo和redo信息记入到事务日志中
3:事务反馈:参与者向协调者发送事务执行结果(成功就是OK,这个时候还没有正式commit)
阶段二:事务提交
只有在所有参与者都返回成功结果时,才会进入事务提交阶段
1:发送提交请求:向所有参与者发出commit请求
2:事务提交:参与者收到commit请求后,正式执行事务提交操作,完成事务提交将释放事务期间占用的资源
3:反馈提交结果:参与者向协调者发送ACK消息
4:协调者接收结果:如果在一定时间内收到所有参与者发送的ACK确认消息,则结束事务,否则进入事务中断阶段
事务中断
如果协调者在任何时候收到了非OK消息(或者在超时后没有接收到所有参与者的响应) 则进入事务中断
1:发送回滚请求:协调者向所有参与者发送rollback请求
2:事务回滚:参与者接收到rollback请求后,会通过阶段一记录的undo信息执行事务回滚操作,回滚成功后释放整个事务执行期间占用的资源
3:反馈回滚结果:参与者在完成回滚之后,向协调者发送ACK消息
4:完成中断:协调者在收到所有参与者的回滚消息后,完成事务中断
2PC的优缺点
优点:原理简单,实现方便
缺点:同步阻塞,单点问题,数据不一致,过于保守
同步阻塞:
在二阶段提交的过程中,所有的节点都在等待其他节点的响应,无法进行其他操作。这种同步阻塞极大的限制了分布式系统的性能。
单点问题:
协调者在整个二阶段提交过程中很重要,如果协调者在提交阶段出现问题,那么整个流程将无法运转,更重要的是:其他参与者将会处于一直锁定事务资源的状态中,而无法继续完成事务操作。
数据不一致:
假设当协调者向所有的参与者发送 commti 请求之后,发生了局部网络异常或者是协调者在尚未发送完所有 commit 请求之前自身发生了崩溃,导致最终只有部分参与者收到了 commit 请求。这将导致严重的数据不一致问题。
过于保守:
如果在二阶段提交的提交询问阶段中,参与者出现故障而导致协调者始终无法获取到所有参与者的响应信息的化,这时协调者只能依靠其自身的超时机制来判断是否需要中断事务,显然,这种策略过于保守。换句话说,二阶段提交协议没有设计较为完善的容错机制,任意一个节点是失败都会导致整个事务的失败。
- 本文标签: 分布式 服务架构
- 本文链接: https://www.php20.cn/article/345
- 版权声明: 本文由仙士可原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权