(转载)全局分布式事务GTS原理以及架构(二)
作者:互联网
GTS核心流程
GTS采用的是基于XA架构优化的技术路线,GTS方案认为XA性能低效主要原因是分布式任务提交设计阻塞(2PC),分布式事务提交的第一阶段等待最慢的一个分支事务完成之后才能完成所有的事务,及时不存在锁的竞争、冲突的情况下,分支数据库连接会被挂起占用的资源不会得到释放来防止全局事务提交前释放资源导致数据不一致。GTS采用的是两个阶段解耦的方式,将提交过程转换成第一阶段本地事务提交+第二阶段异步清理方式。可以有效的释放资源,不必占用数据库的连接资源。同事GTS维护了应用级别的日志与锁的信息,实现全局事务的回滚以及并发控制
GTS示意图
GTS全局事务处理流程与XA一致,也包括全局事务注册、数据访问与全局事务提交三个步骤,但在第二步与第三步的内部处理上与XA不同:
第二步数据访问中,各事务分支完成数据操作的同时,会将全局事务信息(锁与日志信息)存储在当前数据库的表中。
第三步全局事务提交中,采用一阶段本地事务提交+二阶段异步清理的方式。首先对各数据库做本地事务的提交,并释放数据库连接等系统资源,然后,向TM发出全局事务提交请求,TM收到请求后,立即返回成功,TM后续实际工作是对各个数据库使用全局事务标识符进行全局事务信息的清理。
GTS与XA在全局事务的故障恢复处理与并发控制采用了不同的实现机制:
XA两阶段协议是基于数据库内核的日志与锁信息实现全局事务的回滚与并发控制。由于GTS一阶段本地事务提交中,会直接提交本地事务并释放连接,此时数据库内核的日志与锁表对全局事务不再有效。在第二步中,GTS会将日志和锁信息存储在表中,当事务本地提交后,日志和锁信息被持久化保存,用于实现全局事务的并发控制与故障恢复。
GTS的故障恢复只有UNDO操作没有REDO操作,日志表中存储了UNDO需要的信息,包括行记录标识、全局事务号、镜像查询语句、操作的前像与操作的后像。当发生故障时,对于已经本地提交的数据库,从UNDO表中找到修改的记录,记录的操作前像和操作后像,使用镜像查询语句从数据库中读取该记录的当前值。如果当前值与记录操作后像相同,则直接使用操作前像进行恢复,否则报警,进行人工处理。
GTS的全局锁表中存储了记录的加锁信息。封锁的粒度是行(记录),锁的类型包括共享锁和互斥锁,对于同一个记录,加锁的规则是共享锁与共享锁不冲突,共享锁与互斥锁冲突、互斥锁与互斥锁冲突。对插入(INSERT)、修改(UPDATE)、删除(DELETE)、更新模式的锁定查询(SELECT… FOR UPDATE) 操作加互斥锁。对于共享模式的锁定查询 (SELECT…LOCK IN SHARE MODE) 操作加共享锁。若没有锁冲突,在GTS锁表中,增加一行记录,表示加锁成功。
GTS的默认隔离级别为读未提交(脏数据),使用SELECT… FOR UPDATE和SELECT…LOCK IN SHARE MODE,可使查询隔离级别提升至读已提交。
GTS处理流程
GTS实现架构
与XA架构相同,GTS架构由应用、事务管理器、资源管理器三个部分组成。资源管理器由事务分支处理模块、镜像查询构造模块、并发控制模块、恢复控制模块,以及存储在数据库中的GTS事务信息(GTS锁表与GTS日志表)等组成。
- 事务分支处理模块:是资源管理器的外部接口,并完成内部各模块的调用。
- 镜像查询构造模块:从Insert、Update、Delete语句,生成该操作对应记录集的镜像查询语句。例如table_name表包含两个字段column1和column2,column1为主键,则镜像查询语句为select column1, column2 from table_name where column1=v1。
- 并发控制模块:基于GTS事务锁表,维护读写并发控制。锁表定义如下:
字段名 | 字段类型 | 字段描述 |
---|---|---|
ID | 整数 | 自增主键 |
TABLE_NAME | 字符串 | 表名 |
KEY_VALUE | 整数 | 数据行ID |
XID | 字符串 | 全局事务标识 |
XLOCK | 整数 | 互斥锁标记 |
SLOCK | 整数 | 共享锁标记 |
BRANCH_ID | 整数 | 事务分支标识 |
- 恢复控制模块:基于GTS日志表,进行故障恢复。 日志表定义如下:
字段名 | 字段类型 | 字段描述 |
---|---|---|
ID | 整数 | 自增主键 |
GMT_CREATE | 时间 | 创建时间 |
GMT_MODIFIED | datetime | 修改时间 |
XID | 整数 | 全局事务ID |
BRANCH_ID | 整数 | 分支事务ID |
ROLLBACK_INFO | longblob | 查询语句、前像与后像 |
STATUS | 整数 | 状态 |
SERVER | 字符串 | 分支所在DB IP |
主要流程序列图
分别描述了insert/delete/update操作、读已提交操作、提交操作和回滚操作等四个操作的序列图(一种可能的实现方式)。
insert/delete/update操作流程序列图
读已提交操作流程序列图
提交操作流程序列图
回滚操作流程序列图
阿里官方案例
GTS产品网站给出了一个交易类事务中最典型的转账案例
- A和B两个用户的数据分别位于一个DRDS实例的两个不同分库中,用50个进程并发进行 A转账给3,每个进程转账10次,每次转账金额在1到10之间随机生成,转账过程中模拟了3%的网络异常,使用GTS事务保证了A和B钱的总数不变。
- 从代码上可看出,只需增加一条开启GTS的sql语句,就将单机事务应用提升至分布式事务,体现出很好的应用灵活性。测试中转账事务执行500次,成功490次,失败10次。转账结束10秒后,查询账户金额总数正确。
2017云栖大会 GTS产品介绍中,给出了使用GTS与不使用事务(1PC)测试对比。下图,GTS比1PC的性能损耗在10%,远远小于2PC方式,表现出优异的性能。
四、GTS的优势与约束
与基于消息队列与TCC补偿模式的分布式事务相比,在性能满足的情况下,GTS更好的应用灵活性与数据一致性:
- 灵活性:数据库应用基本实现零修改,同时,基于XA模型,可方便的支持消息队列数据库等多种RM。
- 数据一致性:GTS 的缺省事务隔离级别为读未提交,该模式下可以达到分布式事务的最大性能,但可能会读到脏数据。对于一致性要求高的应用,在性能允许的情况下,可以采用已提交读语句(for update、lock in share mode)将隔离级别提升至读已提交。
根据GTS实现机制的特点,其应用场景上有以下约束:加锁操作记录数量不能太大,操作冲突不能太多,加锁时间不能太长。违法以上约束时,GTS内部会占用过多资源、锁冲突和回滚增加,导致性能的下降。电商、物流、金融、零售行业中的核心交易场景有着高并发,高性能,单次操作数据集小,事务响应时间敏感的特点,GTS类方案在此类场景中有着广泛和良好的应用前景。
五、参考书
- 《企业IT架构转型之道》第六章
seata:
探秘蚂蚁金服分布式事务 Seata 的AT、Saga和TCC模式
专利
- CN201510111872-一种分布式事务处理方法及系统
- CN201510111986-一种分布式事务处理方法及系统
网页
标签:事务,架构,GTS,提交,操作,全局,分布式 来源: https://blog.csdn.net/u013099854/article/details/112433126