导览
本大节次要介绍 ShardingSphere 分布式事务的实现原理
- 两阶段 XA 事务
- Seata 柔性事务
两阶段事务 -XA
- 实现原理
实现原理
ShardingSphere 里定义了分布式事务的 SPI 接口 ShardingTransactionManager,Sharding-JDBC 和 Sharding-Proxy 为分布式事务的两个接入端。XAShardingTransactionManager 为分布式事务的 XA 实现类,通过引入 sharding-transaction-xa-core 依赖,即可退出 ShardingSphere 的分布式事务生态中。XAShardingTransactionManager 次要负责对 actual datasource 进行治理和适配,并且将接入端事务的 begin/commit/rollback 操作委托给具体的 XA 事务管理器。
1.Begin(开启 XA 全局事务)
通常收到接入端的 set autoCommit= 0 时,XAShardingTransactionManager 会调用具体的 XA 事务管理器开启 XA 的全局事务,通常以 XID 的模式进行标记。
2. 执行物理 SQL
ShardingSphere 进行解析 / 优化 / 路由后,会生成逻辑 SQL 的分片 SQLUnit,执行引擎为每个物理 SQL 创立连贯的同时,物理连贯所对应的 XAResource 也会被注册到以后 XA 事务中,事务管理器会在此阶段发送 XAResource.start 命令给数据库,数据库在收到 XAResource.end 命令之前的所有 SQL 操作,会被标记为 XA 事务。
例如:
XAResource1.start ## Enlist 阶段执行
statement.execute(“sql1”); ## 模仿执行一个分片 SQL1
statement.execute(“sql2”); ## 模仿执行一个分片 SQL2
XAResource1.end ## 提交阶段执行
这里 sql1 和 sql2 将会被标记为 XA 事务。
3.Commit/rollback(提交 XA 事务)
XAShardingTransactionManager 收到接入端的提交命令后,会委托理论的 XA 事务管理进行提交动作,这时事务管理器会收集以后线程里所有注册的 XAResource,首先发送 XAResource.end 指令,用以标记此 XA 事务的边界。接着会顺次发送 prepare 指令,收集所有参加 XAResource 投票,如果所有 XAResource 的反馈后果都是 OK,则会再次调用 commit 指令进行最终提交,如果有一个 XAResource 的反馈后果为 No,则会调用 rollback 指令进行回滚。在事务管理器收回提交指令后,任何 XAResource 产生的异样都会通过 recovery 日志进行重试,来保障提交阶段的操作原子性,和数据强一致性。
例如:
XAResource1.prepare ## ack: yes
XAResource2.prepare ## ack: yes
XAResource1.commit
XAResource2.commit
XAResource1.prepare ## ack: yes
XAResource2.prepare ## ack: no
XAResource1.rollback
XAResource2.rollback
SAGA 柔性事务
- 实现原理
实现原理
Saga 柔性事务的实现类为 SagaShardingTransactionMananger, ShardingSphere 通过 Hook 的形式拦挡逻辑 SQL 的解析和路由后果,这样,在分片物理 SQL 执行前,能够生成逆向 SQL,在事务提交阶段再把 SQL 调用链交给 Saga 引擎解决。
1.Init(Saga 引擎初始化)
蕴含 Saga 柔性事务的利用启动时,saga-actuator 引擎会依据 saga.properties 的配置进行初始化的流程。
2.Begin(开启 Saga 全局事务)
每次开启 Saga 全局事务时,将会生成本次全局事务的上下文(SagaTransactionContext),事务上下文记录了所有子事务的正向 SQL 和逆向 SQL,作为生成事务调用链的元数据应用。
3. 执行物理 SQL
在物理 SQL 执行前,ShardingSphere 依据 SQL 的类型生成逆向 SQL,这里是通过 Hook 的形式拦挡 Parser 的解析后果进行实现。
4.Commit/rollback(提交 Saga 事务)
提交阶段会生成 Saga 执行引擎所需的调用链路图,commit 操作产生 ForwardRecovery(正向 SQL 弥补)工作,rollback 操作产生 BackwardRecovery 工作(逆向 SQL 弥补)。
SEATA 柔性事务
- 实现原理
实现原理
整合 Seata AT 事务时,须要把 TM,RM,TC 的模型融入到 ShardingSphere 分布式事务的 SPI 的生态中。在数据库资源上,Seata 通过对接 DataSource 接口,让 JDBC 操作能够同 TC 进行 RPC 通信。同样,ShardingSphere 也是面向 DataSource 接口对用户配置的物理 DataSource 进行了聚合,因而把物理 DataSource 二次包装为 Seata 的 DataSource 后,就能够把 Seata AT 事务融入到 ShardingSphere 的分片中。
1.Init(Seata 引擎初始化)
蕴含 Seata 柔性事务的利用启动时,用户配置的数据源会按 seata.conf 的配置,适配为 Seata 事务所需的 DataSourceProxy,并且注册到 RM 中。
2.Begin(开启 Seata 全局事务)
TM 管制全局事务的边界,TM 通过向 TC 发送 Begin 指令,获取全局事务 ID,所有分支事务通过此全局事务 ID,参加到全局事务中;全局事务 ID 的上下文寄存在以后线程变量中。
3. 执行分片物理 SQL
处于 Seata 全局事务中的分片 SQL 通过 RM 生成 undo 快照,并且发送 participate 指令到 TC,退出到全局事务中。ShardingSphere 的分片物理 SQL 是按多线程形式执行,因而整合 Seata AT 事务时,须要在主线程和子线程间进行全局事务 ID 的上下文传递,这同服务间的上下文传递思路完全相同。
4.Commit/rollback(提交 Seata 事务)
提交 Seata 事务时,TM 会向 TC 发送全局事务的 commit 和 rollback 指令,TC 依据全局事务 ID 协调所有分支事务进行 commit 和 rollback。