在了解以上3部分内容后,我们来看一下DDB的分布式事务是如何处理。
首先,DDB用的MySQL不是5.7.7及以上,所以之前提的两个问题理论都会存在。
不过,咱们网易还是牛牛的,针对准备阶段事务被回滚问题制作了专门的MySQL补丁; 针对宕机后提交悬挂事务没有记录binlog继而引起主从数据不一致问题,通过姜承尧的博客发现也已修复。
在网易的MySQL分支版本InnoSQL中,已经对该问题进行了修复。修复的方案很简单,PREPARE成功的事务写日志,但并不是写在二进制日志中,而是写在每个对应分布式事务的单独文件中。
名词说明
DDB:网易分布式数据库
DBI:数据库驱动,也是DTP模型中的TM
DBN:数据库节点
Master:管理服务器(负责兜底处理悬挂事务,还包含其他职责,这里不关心)
(摘自《网易分布式数据库用户手册.pdf》)
结合着我对反编译代码的理解,我们关注下细节。
DDB XA异常恢复
失败重试
对于二阶段操作失败,为避免应用长时间被阻塞,DBI会先起一个异步线程用于重试二阶段的操作,并根据一阶段协商的结果立即返给应用。 当暂时性故障恢复后,事务数据最终一致。如果异步线程重试时间超时(async_timeout参数),则会将异常分支事务信息交给Master统一处理 (这可以解决DBN节点与应用之间网络链路失效导致的故障)
重启DBI恢复
重启后,会先从日志中解析未完成的事务(这里只有提交的,不存在回滚的),发送到Master,请求Master进行悬挂事务提交,再DONE本地日志。
Master代理处理
Master收到DBI发来的悬挂事务信息会先进行3次尝试(xab_retry_times参数,默认3),如果还失败就记录到sysdb的xa表(事务状态XAB_STATUS_NOT_FOUND)。
Master定期检查
对于悬挂事务,可以保守的等待DBI重启后恢复二阶段操作(会引起资源锁)。 也可以积极一点,让master开启定时器(check_suspend_xa参数),自动对悬挂事务进行诊断处理, Master会定期处理所有悬挂事务,根据DBI上报的操作(commit/rollback)来决定提交、回滚悬挂事务。可能会引起数据不一致 (对于那些完成一阶段准备,部分节点完成二阶段提交,部分节点提交失败,异步尝试提交也不成功,还没来得及上报Master或上报失败的场景,Master会直接回滚这些悬挂事务)。
DDB XA其他优化
延迟启动分支事务
在开始全局事务时DBI不会立即在每个DBN节上开始一个分支事务,而是在事务中第一次真正需要访问某个DBN时才在此节点上开始分支事务。 最大限度减少了分布式事务操作数量和参与分布式事务的数据库节点数,提高了分布式事务处理性能。
并发执行分支事务
分布式事务的准备、提交、回滚等操作都通过多个事务子线程并行执行。
写日志优化
在深入理解二阶段协议中我们会发现一个分布式事务要写3次日志,开始提交日志、完成一阶段日志、完成二阶段日志。 DDB中对prepare成功的,写日志优化成2次,对于prepare失败直接就不写日志了(这时候发生故障怎么恢复?留给大家想想)。
日志成组提交
在写prepare日志时并不是在主线程中直接调用fsync将日志刷出到磁盘上,而是等待一个定时刷日志线程来刷日志 (默认是每50ms刷一次,buffer_flush_interval参数)。这样,即使对于很高并发度的应用,写日志也不过每秒调用20次左右的fsync。
二阶段优化为一阶段
通常分布式事务在提交时总是采用二阶段提交策略。
对采用一阶段提交的分布式事务不记录事务日志,二阶段提交需要在prepare和commit成功时分别记录日志(prepare日志需要同步到磁盘)。
经以上分析,DDB的设计真心不错,尽最大可能保证事务的一致性,但依然会存在数据不一致的情况。
针对二阶段提交的优化还可以做的更彻底。 如果在全局事务中某个RM是只读的,可以让这个RM脱离当前全局事务,使用一阶段提交。减少全局事务中的参与者数量。
对于二阶段操作时协调者宕机造成事务悬挂的问题,事实上在DBI模式中,应用频繁升级,这种问题是有一定概率出现的。 是否可以引入高性能分布式日志系统代替本地日志系统记录事务协调日志, Master监听DBI节点,及时接管宕机的原始协调者DBI,Master作为全局兜底协调者,根据分布式日志对悬挂事务进行恢复,理论上是可行的。
组件架构
详细流程
在分布式系统中,如果期望达到数据的强一致性,可用性就没什么保证。
真的没办法构建一个兼顾CAP三者的系统。 我们是否愿意为强一致性付出代价?付出多大代价? 在实际应用中我们更多追求的是数据的弱一致性或最终一致性,为了强一致性而放弃可用性是不可取的。 需要我们去权衡、取舍。
近几年基于分布式一致性算法Paxos及其变种算法的工程实践越来越多,比如阿里的AliSQL X-Cluster,X-DB,OceanBase,微信的PhxSQL,谷歌的Spanner,Ping CAP的tiDB等, 具有强一致高可用,大家有兴趣也可以了解下。
本文来自网易实践者社区,经作者陈志良授权发布。