经典的两阶段提交算法原理及缺陷
背景
笔者在过去经典的两阶段提交算法过程中,发现会遇上部分节点在执行事务提交期间发生故障,导致如下的错误,这些错误都会导致用户数据丢失或者出错。错误如下:
1、一个分布式事务的一部分事务分支被提交,另一部分事务分支被回滚
2、应答给客户端事务提交成功,但是分布式事务所有分支全部被回滚
3、应答给客户端事务被回滚,但是分布式事务部分或者全部分支被提交
4、存储节点故障恢复时,某个存储节点的事务分支不能被正确地恢复。
在上面这些错误源中,第 #4 类错误处理由存储节点自身负责,分布式事务处理机制负责处理前 3 类错误,笔者会在下篇文章做主要讨论。
对于第 #4 类错误,笔者曾经在 FOSDEM 2021 做过一次技术分享,https://fosdem.org/2021/schedule/event/mysql_xa/,国内视频连接在:昆仑分布式数据库 MySQL XA 事务处理的容灾技术(https://b23.tv/h7zzmR)以后也会陆续撰文详述。
经典的两阶段提交算法原理
两阶段提交算法把事务的提交分为 preapre 和 commit 两个阶段。
第一阶段事务管理器 GTM 发送 prepare 命令给所有的 resourcemanager(RM),每个 RM 就 prepare 分布式事务的本地分支,也就是把它们的 WAL 日志刷盘以便即使 RM 宕机,恢复之后仍然可以提交(或者回滚)这些 prepared 状态的事务。
prepare 一个事务之后,这个事务进入 prepared 状态,之后既可以 commit 它,也可以 rollback 它。
如果 GTM 收到所有的 RM 返回的都是成功,那么 GTM 发送 commit 给每个参与的 RM,于是 RM 就提交其 prepared 状态的事务分支,这样就完成了两阶段提交。
经典的两阶段提交算法缺陷
如果两阶段提交流程中发生 GTM 或者 RM 宕机等故障,那么这个两阶段提交流程就可能中断并且无法正确地继续的问题。
如何优化避免其缺陷?
为避免此类事故发生,昆仑分布式数据库的分布式事务处理机制基于经典的两阶段提交算法,并在此基础上增强了其容灾能力和错误处理能力。
故此可以做到任意时刻昆仑数据库集群的任意节点宕机或者网络故障、超时等都不会导致集群管理的数据发生不一致或者丢失等错误。
一个昆仑分布式数据库集群包含若干个彼此独立且功能相同的计算节点做分布式事务处理和分布式查询处理(下篇文章做详述):
包含若干个存储集群存储用户数据分片,每个存储集群使用高可用机制确保节点宕机数据不丢失。
一个结构与存储集群完全相同的元数据集群,它存储着这个集群的关键元数据信息,包括本文所说的 commit log。
一个 cluster_mgr 模块, 负责维护集群运行状态,并且处理因为节点故障而残留的 prepared 状态的事务分支。
故此在上述的模块的有机配合下,经典的两阶段算法提交的缺陷可以很好的避免!
总结
对于经典的两阶段提交算法流程,笔者及团队已经做了优化用于解决这些问题,从而达到坚不可摧的容灾能力。对于优化的原理过程,笔者会在下文做详述(届时欢迎大家做讨论)
需要技术支持可以微信搜索微信号(KunLunDB-Linda),添加客服,在线沟通即可。
END
版权声明: 本文为 InfoQ 作者【KunlunDB】的原创文章。
原文链接:【http://xie.infoq.cn/article/db742e0183910d9c43af38507】。文章转载请联系作者。
评论