XA规范
包含角色
- Application:应用程序
- TM:Transaction Manager,事务管理器
- RM:Resource Manager,资源管理器
CRM:Communication Resource Manager,通信资源管理器
XA分布式事务架构
XA:接口规范
- TM和RM通信的规范:怎么提交事务、怎么会滚事务
2PC理论
- 基于XA规范落地的分布式事务,定义了更多的细节
-
事务执行流程
阶段一(prepared)
TM接收到应用程序发过来的事务后,将事务中的多个SQL发送给对应RM,即prepared消息
- RM在此阶段只去执行sql,不提交事务
-
阶段二(committed)
如果所有的RM都返回成功,则通知RM提交事务
-
使用场景
适合单块系统跨多库的场景
-
缺陷
同步阻塞
在阶段一里执行prepared操作会占用资源,一直到整个分布式事务完成才会释放
-
单点故障
-
事务状态丢失
假如把TM做成双机热备,一个挂了,使用另外一个,但新进来的并不知道当前的事务状态,不知道哪个库committed哪个没有
3PC
事务执行流程
阶段一:canCommitted
TM发送canCommitted消息给RM,次阶段主要是网络和各数据库状态是否正常
阶段二:preCommitted
- 同2PC的阶段一
- 如果一个库收到了preCommitted,则说明其他库也都收到了,这正是因为canCommitted阶段成功了
阶段三:doCommitted
- 同2PC的阶段二
如果某个库preCommitted响应成功后,超时未收到doCommitted,则也会执行本地committed操作
缺陷
如果阶段二中一个库资源所动失败,返回失败给TM,则TM会发送abort给所有TM,通知其释放资源
但如果一个TM因为网络原因没有收到abort,则会超时执行本地committed操作,导致数据异常
TCC
阶段
try
confirm
cancel
-
问题
-
场景
资金相关的场景等核心场景
短事务场景,因为一个TCC事务中包含了很多同步调用,如果有的调用耗时比较长,则会影响性能
通用型方案
角色
主业务服务
- TCC事务的主控服务,负责整个事务的执行、提交、会滚
- 从业务服务
- 提供try(锁定资源)
- 比如是A用户给B用户转账100,此阶段就先从用户A的账户扣掉100,在一张临时表里插入这100的记录,状态为锁定状态或扣款中
- confirm(执行业务逻辑)
- B用户账户加上100,临时表里的100元状态为结束/完成状态
- cancel(回滚)接口
- 就A用户账户再加上100元,临时表中的100元记录状态为取消/失败状态
- 提供try(锁定资源)
业务管理器
主业务服务执行本地事务,但事务未提交
- 主业务服务相业务管理器,申请创建分布式事务
- 主业务服务向业务管理器,注册各个从业务服务
- 主业务服务调用从业务服务的try接口
- 如果try接口调用失败,主业务服务会滚本地事务
- 通知主业务管理器调用从业务的cancel接口
主业务服务提交本地事务,接着通知业务管理器调用从业务的confirm接口
注意事项
要把绝大多数的业务逻辑在 Try 阶段完成,在 Try 阶段做尽可能多的事情;Confirm/Cancel只通过最简单的代码释放冻结资源
- 空回滚:try阶段可能网络问题失败了,没有执行资源锁定,这时候如果执行cancel接口,要注意不能瞎搞
- try回滚/confirm回滚:根据当前从业务分布式事务状态,进行对应的回滚
- 倒置请求(超时处理):如果一个从业务的ty调用超时,结果执行了cancel,但过了一会try请求来了,此时应该不允许处理;confirm超时同理
- 接口幂等性:try- confirm- cancel接口可能会被重试调用
confirm或cancel多次重试失败:需要开发额外的数据完整性校验程序补救;人工补救
TCC分布式事务框架
ByteTCC
-
异步确保型TCC方案
对上述的通用型方案进行改造
-
可靠消息服务
try:在本地数据库插入一条消息记录
- confirm:根据本地记录,调用从业务的接口
-
优点
-
缺点
-
补偿性TCC方案
从业务接口
do接口
- 从业务本地业务逻辑
compensate接口
AT模式的“手动版”
代码实现
TM端开启全局事务
@GlobalTransactional
public void sale(){ //商城业务中销售商品方法
orderAction.prepare("张三",30);
storageAction.prepare("可乐",10);
}
RM的锁定资源方法上(如上的prepare方法)添加@TwoPhaseBusinessAction注解: @TwoPhaseBusinessAction 注解,声明 prepare 方法执行成功或失败后由哪个方法进行后续的提交或回滚,这个注解有三个参数:
- name 代表分支事务的注册名称;
- commitMethod 代表二阶段 TC 发来提交消息时执行哪个方法;
rollbackMethod 代表二阶段 TC 发来回滚消息时执行哪个方法。
public interface OrderAction { @TwoPhaseBusinessAction(name="TccOrderAction",commitMethod = "commit" , rollbackMethod = "rollback") //prepare对应TCC阶段一,用于锁定资源。 public boolean prepare(BusinessActionContext actionContext, @BusinessActionContextParameter(paramName = "customer") String customer, @BusinessActionContextParameter(paramName = "amount") float amount ); //提交方法定义 public boolean commit(BusinessActionContext actionContext); //回滚方法定义 public boolean rollback(BusinessActionContext actionContext); }
BusinessActionContext:TCC事务的上下文对象
- BusinessActionContextParameter:注解标记的参数会在上下文中传播,即能通过BusinessActionContext对象在commit方法及cancle方法中取到该参数值
- String orderCode = (String)actionContext.getActionContext(“orderCode”);