开篇

 这篇文章的目的主要是讲解Fescar TC执行commit的流程,目的是讲解清楚commit流程中的一些步骤。

 遗憾的是因为commit本身Fescar的分支事务注册上报,如果事先不了解Fescar的分支事务,有些逻辑理解起来会有一些奇怪,对于branchSession本身还未了解,所以只能单独讲解commit流程。

背景


说明:

  • 分支事务中数据的 本地锁 由本地事务管理,在分支事务 Phase1 结束时释放。
    同时,随着本地事务结束,连接 也得以释放。
  • 分支事务中数据的 全局锁 在事务协调器侧管理,在决议 Phase2 全局提交时,全局锁马上可以释放。只有在决议全局回滚的情况下,全局锁 才被持有至分支的 Phase2 结束。

这个设计,极大地减少了分支事务对资源(数据和连接)的锁定时间,给整体并发和吞吐的提升提供了基础。

这里需要重点指出的是:Phase1阶段的commit()操作是各个分支事务本地的事务操作。Phase2阶段的操作是全局的commit()和rollback()。TC-commit流程指的就是Phase2阶段。

TC commit流程介绍

  • 1.根据transactionId查找begin阶段生成的GlobalSession对象。
  • 2.对GlobalSession对象进行清理操作,删除分支事务的锁并清理GlobalSession对象。
  • 3.TC通知所有RM(各分支事务的资源管理器)进行全局提交操作(doGlobalCommit)。

TC commit源码分析

public class DefaultCoordinator extends AbstractTCInboundHandlerimplements TransactionMessageHandler, ResourceManagerInbound {@Overrideprotected void doGlobalCommit(GlobalCommitRequest request, GlobalCommitResponse response, RpcContext rpcContext)throws TransactionException {response.setGlobalStatus(core.commit(XID.generateXID(request.getTransactionId())));}
}

说明:

  • DefaultCoordinator的doGlobalCommit()作为全局回滚入口
  • core.commit()根据XID去执行全局commit()操作。

Commit 主流程

public class DefaultCore implements Core {public GlobalStatus commit(String xid) throws TransactionException {// 1.查找GlobalSessionGlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid));if (globalSession == null) {return GlobalStatus.Finished;}GlobalStatus status = globalSession.getStatus();// 2.关闭全局session并执行清理工作globalSession.closeAndClean(); // Highlight: Firstly, close the session, then no more branch can be registered.// 3.执行GlobalCommit通知动作if (status == GlobalStatus.Begin) {if (globalSession.canBeCommittedAsync()) {asyncCommit(globalSession);} else {doGlobalCommit(globalSession, false);}}// 返回GlobalCommit后的状态return globalSession.getStatus();}
}

说明:

  • DefaultCore是全局回滚的核心逻辑。
  • SessionHolder.findGlobalSession查找全局的GlobalSession对象。
  • GlobalSession执行closeAndClean操作。
  • DefaultCore执行doGlobalCommit通知TC执行全局回滚操作。

查找GlobalSession

public class SessionHolder {public static GlobalSession findGlobalSession(Long transactionId) throws TransactionException {return getRootSessionManager().findGlobalSession(transactionId);}
}public class DefaultSessionManager extends AbstractSessionManager {}public abstract class AbstractSessionManager implements SessionManager, SessionLifecycleListener {protected Map<Long, GlobalSession> sessionMap = new ConcurrentHashMap<>();public GlobalSession findGlobalSession(Long transactionId) throws TransactionException {return sessionMap.get(transactionId);}
}

说明:

  • findGlobalSession()方法从DefaultSessionManager当中获取GlobalSession。
  • DefaultSessionManager的父类AbstractSessionManager的findGlobalSession从sessionMap获取GlobalSession对象。

GlobalSession的closeAndClean

public class GlobalSession implements SessionLifecycle, SessionStorable {public void closeAndClean() throws TransactionException {close();clean();}public void close() throws TransactionException {if (active) {for (SessionLifecycleListener lifecycleListener : lifecycleListeners) {lifecycleListener.onClose(this);}}}private void clean() throws TransactionException {for (BranchSession branchSession : branchSessions) {branchSession.unlock();}}
}public class DefaultSessionManager extends AbstractSessionManager {}
public abstract class AbstractSessionManager implements SessionManager, SessionLifecycleListener {public void onClose(GlobalSession globalSession) throws TransactionException {globalSession.setActive(false);}
}

说明:

  • GlobalSession的执行closeAndClean操作,先执行close再执行clean。
  • lifecycleListener.onClose()执行DefaultSessionManager的onClose()。
  • DefaultSessionManager的onClose()把设置active标识为false。
  • clean()操作对所有的分支事务branchSession释放锁。这部分逻辑比较复杂单独列出。

BranchSession的unlock

public class BranchSession implements Lockable, Comparable<BranchSession>, SessionStorable {public boolean unlock() throws TransactionException {if (lockHolder.size() == 0) {return true;}Iterator<Map.Entry<Map<String, Long>, Set<String>>> it = lockHolder.entrySet().iterator();while (it.hasNext()) {Map.Entry<Map<String, Long>, Set<String>> entry = it.next();Map<String, Long> bucket = entry.getKey();Set<String> keys = entry.getValue();synchronized (bucket) {for (String key : keys) {Long v = bucket.get(key);if (v == null) {continue;}if (v.longValue() == getTransactionId()) {bucket.remove(key);}}}}lockHolder.clear();return true;}
}

说明:

  • BranchSession的unlock()操作对BranchSession 进行清理。
  • BranchSession内部的数据由于暂未阅读该部分代码所以暂时不能解释清楚。
  • 全局清除lockHolder。

TC执行GlobalCommit

public class DefaultCore implements Core {public void doGlobalCommit(GlobalSession globalSession, boolean retrying) throws TransactionException {// 遍历所有的BranchSession执行回滚操作for (BranchSession branchSession : globalSession.getSortedBranches()) {BranchStatus currentStatus = branchSession.getStatus();if (currentStatus == BranchStatus.PhaseOne_Failed) {continue;}try {BranchStatus branchStatus = resourceManagerInbound.branchCommit(XID.generateXID(branchSession.getTransactionId()), branchSession.getBranchId(),branchSession.getResourceId(), branchSession.getApplicationData());switch (branchStatus) {case PhaseTwo_Committed:globalSession.removeBranch(branchSession);continue;case PhaseTwo_CommitFailed_Unretryable:if (globalSession.canBeCommittedAsync()) {LOGGER.error("By [{}], failed to commit branch {}", branchStatus, branchSession);continue;} else {globalSession.changeStatus(GlobalStatus.CommitFailed);globalSession.end();LOGGER.error("Finally, failed to commit global[{}] since branch[{}] commit failed",globalSession.getTransactionId(), branchSession.getBranchId());return;}default:if (!retrying) {queueToRetryCommit(globalSession);return;}if (globalSession.canBeCommittedAsync()) {LOGGER.error("By [{}], failed to commit branch {}", branchStatus, branchSession);continue;} else {LOGGER.error("Failed to commit global[{}] since branch[{}] commit failed, will retry later.",globalSession.getTransactionId(), branchSession.getBranchId());return;}}} catch (Exception ex) {LOGGER.info("Exception committing branch {}", branchSession, ex);if (!retrying) {queueToRetryCommit(globalSession);if (ex instanceof TransactionException) {throw (TransactionException) ex;} else {throw new TransactionException(ex);}}}}if (globalSession.hasBranch()) {return;}globalSession.changeStatus(GlobalStatus.Committed);globalSession.end();}
}

说明:

  • 对所有的BranchSession执行branchCommit通知
  • 针对branchCommit返回状态进行判断,有一些逻辑在里面,后续阅读了Branch相关资料后再补充状态转移图。

Fescar TC-commit流程相关推荐

  1. Fescar TC-rollback流程

    开篇  这篇文章的目的主要是讲解Fescar TC执行rollback的流程,目的是讲解清楚rollback流程中的一些步骤.  遗憾的是因为rollback本身涉及Fescar的分支事务注册上报,如 ...

  2. Fescar TC-beigin流程

    开篇  这篇文章是用来讲解清楚TC(Transaction Coordinator:事务协调器)在处理TM发送过来的begin操作(事务开启操作).  核心逻辑包括GlobalSession对象的生成 ...

  3. Fescar锁和隔离级别的理解

    Fescar全局锁的理解 前几天夜里,我老大发我一篇文章说阿里的GTS开源了. 因为一直对分布式事务比较感兴趣,立马pull了代码,进行阅读.基本的原理,实现方案我就不一一细化了,详细见官方文档(写的 ...

  4. Fescar 源码解析系列

    为什么80%的码农都做不了架构师?>>> Fescar example介绍 Fescar example解析 - TM流程 Fescar example解析 - GlobalTran ...

  5. mysql commit 机制_1024MySQL事物提交机制

    转自 http://www.cnblogs.com/exceptioneye/p/5451960.html MySQL作为一种关系型数据库,已被广泛应用到互联网中的诸多项目中.今天我们来讨论下事务的提 ...

  6. GRS认证跟TC证有何区别

    [GRS认证跟TC证有何区别] GRS是全球回收利用规范,英文名字:GLOBALRecycledStandard(通称GRS验证)是全球化.自行化.完备的产品执行标准.供应链管理生产商操纵产品回收/再 ...

  7. 每日一问:谈谈 SharedPreferences 的 apply() 和 commit()

    SharedPreferences灵魂拷问之原理 先来一波灵魂追问: 听说提交要用apply(),为什么? 和commit()什么区别? 跨进程怎么操作? 会堵塞主线程吗? 很着急有替代方案吗? (  ...

  8. Deepin RISCV 修包流程问题总结

    Deepin RISCV 修包流程问题总结 该文写于 PLCT deepin 小队实习期间,总结修包过程中遇到的一些小问题和解决方案.方便之后修包过程中快速解决同样的问题,也希望能帮助到和笔者一样的小 ...

  9. mysql 存储过程 commit_mysql 存储过程commit

    MySQL并发复制系列一:binlog组提交 MySQL  Binary log在MySQL 5.1版本后推出主要用于主备复制的搭建,我们回顾下MySQL 在开启/关闭 Binary Log功能时是如 ...

最新文章

  1. springMVC--(讲解5)文件上传与传参测试
  2. 使用ado直接连接mysql_使用ADO直接连Mysql ,不经过ODBC
  3. tomcat 设置虚拟路径
  4. android 电池栏的高度,Android如何取得状态栏、任务栏高度
  5. 【C#程序设计】教学讲义——第三章:C#语言基础
  6. 刷题总结——序列操作(权值线段树套树状数组)
  7. python接口测试实战_Python接口测试实战01:七种武器
  8. java dubbo swagger_Dubbo 的 Swagger 服务文档 swagger-dubbo
  9. Convert.ToString和ToString的区别
  10. Asp.net对http request 处理的全过程!
  11. 在android下使用i2c tools
  12. 安卓地图的实现附源码
  13. php 获取城市列表接口,省份城市区域列表
  14. win10熄屏时间不对_win10设置了息屏时间但是很快就息屏
  15. 美团搜索多业务商品排序探索与实践
  16. 微信扫码/链接下载APK包, 自定义引导页,引导在外部浏览器打开
  17. CQOI2007]涂色paint(BZOJ 1260) 区间动态规划 DP 逆向思维
  18. @property详细解读
  19. 批处理的加密,批处理乱码的查看
  20. C# 对Excel表格中的数据进行排序

热门文章

  1. Spring5源码 - 05 invokeBeanFactoryPostProcessors 源码解读_2
  2. Quartz-Job 详解
  3. HTML基础_Day01
  4. 涉密计算机网络与互联网及其,涉密计算机及网络与互联网及其他公共信息网络必须隔离 - 作业在线问答...
  5. 复习(二)—— Makefile工具使用
  6. Compliments 计算机术语,2016年9月统考计算机复习题.doc
  7. react 和 lodash 完美结合命令
  8. php 树形结构实例,如果用php写树形结构?
  9. mysql索引 钱缀_【mysql索引】之前缀索引-Go语言中文社区
  10. Mysql主从异常 表被回滚_oracle表回滚到一个指定时间的操作语句 oracle 误删除数据恢复...