Day06 Druid 的事务实现
今天分析下 pool 下的 xa 包:package com.alibaba.druid.pool.xa;
一、XA 协议
XA 协议是由 X/Open 组织提出的分布式事务处理规范,主要定义了事务管理器 TM 和局部资源管理器 RM 之间的接口。Mysql 从 5.0 版本开始,InnoDB 存储引擎已经支持 XA 协议。
1. 两阶段提交
分布式事务的两阶段提交是把整个事务提交分为 prepare 和 commit 两个阶段:
第一阶段,事务协调者向事务参与者发送 prepare 请求,事务参与者收到请求后,如果可以提交事务,回复 yes,否则回复 no。
第二阶段,如果所有事务参与者都回复了 yes,事务协调者向所有事务参与者发送 commit 请求,否则发送 rollback 请求。
两阶段提交存在三个问题:
- 同步阻塞,本地事务在 prepare 阶段锁定资源,如果有其他事务需要访问锁定的资源,就必须等待前面的事务完成。这样就造成了系统性能下降。
- 协调节点单点故障,如果第一个阶段 prepare 成功了,但是第二个阶段协调节点发出 commit 指令之前宕机了,所有服务的数据资源处于锁定状态,事务将无限期地等待。
- 数据不一致,如果第一阶段 prepare 成功了,但是第二阶段协调节点向某个节点发送 commit 命令时失败,就会导致数据不一致。
2. 三阶段提交
为了解决两阶段提交的问题,三阶段提交做了改进:
- 协调节点、事务参与者都引入了超时机制
- 第一阶段的 prepare 阶段分成了两步,canCommi 和 preCommit。
引入 preCommit 阶段后,协调节点会在 commit 之前再次检查各个事务参与者的状态,保证它们的状态是一致的。但是也存在问题,那就是如果第三阶段发出 rollback 请求,有的节点没有收到,那没有收到的节点会在超时之后进行提交,造成数据不一致。
接下来看看 Druid 中 分布式事务的实现。
二、JtdsXAResource
类
JtdsXAResource
类实现了 XAResource
接口, XAResource
接口位于 javax.transaction.xa
包下,提供了事务相关的功能封装:
package javax.transaction.xa;
public interface XAResource {
int TMENDRSCAN = 8388608;
int TMFAIL = 536870912;
int TMJOIN = 2097152;
int TMNOFLAGS = 0;
int TMONEPHASE = 1073741824;
int TMRESUME = 134217728;
int TMSTARTRSCAN = 16777216;
int TMSUCCESS = 67108864;
int TMSUSPEND = 33554432;
int XA_RDONLY = 3;
int XA_OK = 0;
// 提交事务
void commit(Xid var1, boolean var2) throws XAException;
// 结束事务
void end(Xid var1