Fescar TC-commit流程
开篇
这篇文章的目的主要是讲解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流程相关推荐
- Fescar TC-rollback流程
开篇 这篇文章的目的主要是讲解Fescar TC执行rollback的流程,目的是讲解清楚rollback流程中的一些步骤. 遗憾的是因为rollback本身涉及Fescar的分支事务注册上报,如 ...
- Fescar TC-beigin流程
开篇 这篇文章是用来讲解清楚TC(Transaction Coordinator:事务协调器)在处理TM发送过来的begin操作(事务开启操作). 核心逻辑包括GlobalSession对象的生成 ...
- Fescar锁和隔离级别的理解
Fescar全局锁的理解 前几天夜里,我老大发我一篇文章说阿里的GTS开源了. 因为一直对分布式事务比较感兴趣,立马pull了代码,进行阅读.基本的原理,实现方案我就不一一细化了,详细见官方文档(写的 ...
- Fescar 源码解析系列
为什么80%的码农都做不了架构师?>>> Fescar example介绍 Fescar example解析 - TM流程 Fescar example解析 - GlobalTran ...
- mysql commit 机制_1024MySQL事物提交机制
转自 http://www.cnblogs.com/exceptioneye/p/5451960.html MySQL作为一种关系型数据库,已被广泛应用到互联网中的诸多项目中.今天我们来讨论下事务的提 ...
- GRS认证跟TC证有何区别
[GRS认证跟TC证有何区别] GRS是全球回收利用规范,英文名字:GLOBALRecycledStandard(通称GRS验证)是全球化.自行化.完备的产品执行标准.供应链管理生产商操纵产品回收/再 ...
- 每日一问:谈谈 SharedPreferences 的 apply() 和 commit()
SharedPreferences灵魂拷问之原理 先来一波灵魂追问: 听说提交要用apply(),为什么? 和commit()什么区别? 跨进程怎么操作? 会堵塞主线程吗? 很着急有替代方案吗? ( ...
- Deepin RISCV 修包流程问题总结
Deepin RISCV 修包流程问题总结 该文写于 PLCT deepin 小队实习期间,总结修包过程中遇到的一些小问题和解决方案.方便之后修包过程中快速解决同样的问题,也希望能帮助到和笔者一样的小 ...
- mysql 存储过程 commit_mysql 存储过程commit
MySQL并发复制系列一:binlog组提交 MySQL Binary log在MySQL 5.1版本后推出主要用于主备复制的搭建,我们回顾下MySQL 在开启/关闭 Binary Log功能时是如 ...
最新文章
- springMVC--(讲解5)文件上传与传参测试
- 使用ado直接连接mysql_使用ADO直接连Mysql ,不经过ODBC
- tomcat 设置虚拟路径
- android 电池栏的高度,Android如何取得状态栏、任务栏高度
- 【C#程序设计】教学讲义——第三章:C#语言基础
- 刷题总结——序列操作(权值线段树套树状数组)
- python接口测试实战_Python接口测试实战01:七种武器
- java dubbo swagger_Dubbo 的 Swagger 服务文档 swagger-dubbo
- Convert.ToString和ToString的区别
- Asp.net对http request 处理的全过程!
- 在android下使用i2c tools
- 安卓地图的实现附源码
- php 获取城市列表接口,省份城市区域列表
- win10熄屏时间不对_win10设置了息屏时间但是很快就息屏
- 美团搜索多业务商品排序探索与实践
- 微信扫码/链接下载APK包, 自定义引导页,引导在外部浏览器打开
- CQOI2007]涂色paint(BZOJ 1260) 区间动态规划 DP 逆向思维
- @property详细解读
- 批处理的加密,批处理乱码的查看
- C# 对Excel表格中的数据进行排序
热门文章
- Spring5源码 - 05 invokeBeanFactoryPostProcessors 源码解读_2
- Quartz-Job 详解
- HTML基础_Day01
- 涉密计算机网络与互联网及其,涉密计算机及网络与互联网及其他公共信息网络必须隔离 - 作业在线问答...
- 复习(二)—— Makefile工具使用
- Compliments 计算机术语,2016年9月统考计算机复习题.doc
- react 和 lodash 完美结合命令
- php 树形结构实例,如果用php写树形结构?
- mysql索引 钱缀_【mysql索引】之前缀索引-Go语言中文社区
- Mysql主从异常 表被回滚_oracle表回滚到一个指定时间的操作语句 oracle 误删除数据恢复...