DDM事务模型
因为DDM中的表一般都做了分库分表,使得这些表中的数据可能分布在很多个RDS实例上的不同数据库分片内。在DDM中一个事务中对各个逻辑表的增删改查很有可能实际发生在多个RDS实例上的不同数据库分片上,每个RDS实例上同一数据库分片内所发生的对分片内数据表的一系列操作相当于一个本地事务,这样DDM层面的事务就相当于由多个RDS实例上的本地事务所组成的分布式事务,这些本地事务要么全部成功,要么全部失败。
DDM的分布式事务实现
DDM中的分布式事务模块基于MySQL XA协议实现,XA协议是对2PC(Two Phase Commit)事务模型的一种实现,2PC是一种经典的分布式事务实现方案。基于MySQL XA协议的分布式事物可以实现强一致性写,整体分布式事物的一致性说明可参考MySQL官方文档。
在分布式系统里,每个参与者都可以知晓自己操作的成功或者失败,却无法知道其他节点操作的成功或失败。当一个事务跨多个节点时,为了保持事务的原子性与一致性,需要引入一个协调者(Coordinator)来统一掌控所有参与者(Participant)的操作结果,并指示它们是否要把操作结果进行真正的提交(commit)或者回滚(rollback)。DDM节点在这个分布式事务中扮演协调者的角色,RDS实例则是参与者。
2PC顾名思义分为两个阶段,其实施思路可概括为:
- 准备阶段(prepare phase):参与者将操作结果通知协调者,参与者如果给出了已准备的回应,则应保证在协调者做出决定之前需要将本次决议所需资源进行预留。
- 提交阶段(commit phase):收到参与者的回应后,协调者再向参与者发出通知,根据反馈情况决定各参与者是否要提交还是回滚。
举例说明:
甲乙丙丁四人要聚餐,需要确定时间,不妨设甲是协调者,乙丙丁是参与者。
准备阶段:
- 甲发短信给乙丙丁,周二中午十二点聚餐是否有时间。
- 丁回复有时间。
- 乙回复有时间。
- 丙迟迟不回复,此时对于这个活动,甲乙丙丁均处于阻塞状态,算法无法继续进行。
- 丙回复有时间(或者没有时间)。
提交阶段:
- 协调者甲将收集到的结果(周二中午聚餐或者不聚餐)反馈给乙丙丁(什么时候反馈,以及反馈结果如何,在此例中取决与丙的时间与决定)。
- 乙收到。
- 丙收到。
- 丁收到。
- 如果有人没有收到,则甲后续不断重新进行通知,直到通知成功。
2PC具体实现
DDM对事务的2阶段提交进行了透明化封装。应用侧使用DDM事务的时候不需要关心底层是否为分布式事务,只需像使用普通事务一样执行BEGIN/COMMIT指令进行事务操作。DDM会自动处理分布式事务的两阶段提交逻辑。如果事务只涉及一个数据分片,那么DDM还可以自动将事务降级为一阶段提交的本地事务。一阶段提交的细节本文不详细展开。
其中XID由节点内事务序号、节点ID和时间戳组成,代表了一个全局维度的分布式事务唯一编号,该编号再加上对应分库名构成实际在物理库上开启分布式事务分支的XA_ID 。
DDM事务使用建议
- 虽然DDM支持分布式事务,但如果能够使事务内所有SQL都带上同一个拆分键,DDM可以把事务优化为单分片事务从而获得更极致的性能。
- DDM事务模型采取2PC分布式事务模型,RDS自身的死锁检测无法避免跨RDS的分布式事务死锁,如遇到lock wait超时则提示可能存在跨分片死锁,请检查业务模型是否存在这方面问题。