摘要: 原創出處 http://www.iocoder.cn/TCC-Transaction/console/ 「芋道源碼」歡迎轉載,保留摘要,謝謝!java
本文主要基於 TCC-Transaction 1.2.3.3 正式版mysql
🙂🙂🙂關注**微信公衆號:【芋道源碼】**有福利:git
- RocketMQ / MyCAT / Sharding-JDBC 全部源碼分析文章列表
- RocketMQ / MyCAT / Sharding-JDBC 中文註釋源碼 GitHub 地址
- 您對於源碼的疑問每條留言都將獲得認真回覆。甚至不知道如何讀源碼也能夠請教噢。
- 新的源碼解析文章實時收到通知。每週更新一篇左右。
- 認真的源碼交流微信羣。
本文分享 運維平臺。TCC-Transaction 提供了相對精簡的運維平臺,用於查看在《TCC-Transaction 源碼分析 —— 事務存儲器》提到的事務存儲。目前暫時只有兩個功能:github
運維平臺( Maven 項目 tcc-transaction-server
) 總體代碼結構以下:redis
本文自下而上,Dao => Controller => UI 的順序進行解析實現。sql
你行好事會由於獲得讚揚而愉悅
同理,開源項目貢獻者會由於 Star 而更加有動力
爲 TCC-Transaction 點贊!傳送門apache
ps:筆者假設你已經閱讀過《tcc-transaction 官方文檔 —— 使用指南1.2.x》。數組
org.mengyun.tcctransaction.server.dao.TransactionDao
,事務Dao 接口,實現代碼以下:微信
public interface TransactionDao {
/** * 得到事務 VO 數組 * * @param domain 領域 * @param pageNum 第幾頁 * @param pageSize 分頁大小 * @return 事務 VO 數組 */
List<TransactionVo> findTransactions(String domain, Integer pageNum, int pageSize);
/** * 得到事務總數量 * * @param domain 領域 * @return 數量 */
Integer countOfFindTransactions(String domain);
/** * 重置事務重試次數 * * @param domain 領域 * @param globalTxId 全局事務編號 * @param branchQualifier 分支事務編號 * @return 是否重置成功 */
boolean resetRetryCount(String domain, byte[] globalTxId, byte[] branchQualifier);
}
複製代碼
TCC-Transaction 提供了四種事務存儲器,可是目前只支持兩種數據訪問層的實現:app
org.mengyun.tcctransaction.server.dao.JdbcTransactionDao
,JDBC 事務 DAO 實現。實現代碼以下:
@Repository("jdbcTransactionDao")
public class JdbcTransactionDao implements TransactionDao {
private static final String TABLE_NAME_PREFIX = "TCC_TRANSACTION";
@Autowired
private DataSource dataSource;
/** * 讀取 jdbc-domain-suffix.properties */
@Value("#{jdbcDomainSuffix}")
private Properties domainSuffix;
// ... 省略代碼
}
複製代碼
dataSource
,數據源。配置方式以下:
// appcontext-server-dao.xml
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="50"/>
<property name="minIdle" value="5"/>
<property name="maxIdle" value="20"/>
<property name="initialSize" value="30"/>
<property name="logAbandoned" value="true"/>
<property name="removeAbandoned" value="true"/>
<property name="removeAbandonedTimeout" value="10"/>
<property name="maxWait" value="1000"/>
<property name="timeBetweenEvictionRunsMillis" value="10000"/>
<property name="numTestsPerEvictionRun" value="10"/>
<property name="minEvictableIdleTimeMillis" value="10000"/>
<property name="validationQuery" value="SELECT NOW() FROM DUAL"/>
</bean>
// tcc-transaction-server.properties
jdbc.url=jdbc:mysql://127.0.0.1:33061/TCC?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456
複製代碼
appcontext-server-dao.xml
,配置數據源 Bean 對象。tcc-transaction-server.properties
,配置數據源屬性。domainSuffix
,domian
和 表後綴( suffix
) 的映射關係。配置方式以下:
// jdbc-domain-suffix.properties
CAPITAL=_CAP
ORDER=_ORD
REDPACKET=_RED
複製代碼
JdbcTransactionDao 代碼實現上比較易懂,點擊連接查看,已經添加中文註釋。
org.mengyun.tcctransaction.server.dao.RedisTransactionDao
,Redis 事務 DAO。實現代碼以下:
@Repository("redisTransactionDao")
public class RedisTransactionDao implements TransactionDao {
/** * redis pool */
@Autowired
private JedisPool jedisPool;
/** * 序列化 */
private ObjectSerializer serializer = new JdkSerializationSerializer();
/** * 讀取 redis-domain-key-prefix.properties */
@Value("#{redisDomainKeyPrefix}")
private Properties domainKeyPrefix;
}
複製代碼
jedisPool
,Redis 鏈接池。配置方式以下:
// appcontext-server-dao.xml
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="300"/>
<property name="maxIdle" value="100"/>
<property name="minIdle" value="10"/>
<property name="maxWaitMillis" value="3000"/>
</bean>
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg index="0" ref="jedisPoolConfig"/>
<constructor-arg index="1" value="${redis.host}"/>
<constructor-arg index="2" value="${redis.port}" type="int"/>
<constructor-arg index="3" value="6000" type="int"/>
<constructor-arg index="4" type="java.lang.String">
<null/>
</constructor-arg>
<constructor-arg index="5" value="${redis.db}" type="int"/>
</bean>
// tcc-transaction-server.properties
redis.host=127.0.0.1
redis.port=6379
redis.password=
redis.db=0
複製代碼
appcontext-server-dao.xml
,配置 Redis 鏈接池 Bean 對象。tcc-transaction-server.properties
,配置 Redis 鏈接池屬性。domainKeyPrefix
,domain 和 Redis Key 前綴( prefix
)的映射。配置方式以下:
CAPITAL=TCC:CAP:
ORDER=TCC:ORD:
REDPACKET=TCC:RED:
複製代碼
RedisTransactionDao 代碼實現上比較易懂,點擊[連接]https://github.com/YunaiV/tcc-transaction/blob/e54c3e43a2e47a7765bdb18a485860cb31acbb72/tcc-transaction-server/src/main/java/org/mengyun/tcctransaction/server/dao/RedisTransactionDao.java)查看,已經添加中文註釋。
org.mengyun.tcctransaction.server.controller.TransactionController
,事務 Controller。實現代碼以下:
@Controller
public class TransactionController {
public static final Integer DEFAULT_PAGE_NUM = 1;
public static final int DEFAULT_PAGE_SIZE = 10;
/** * 數據訪問對象 */
@Autowired
@Qualifier("jdbcTransactionDao")
private TransactionDao transactionDao;
/** * 項目訪問根目錄 */
@Value("${tcc_domain}")
private String tccDomain;
}
複製代碼
transactionDao
,數據訪問對象。配置方式以下:
// appcontext-server-dao.xml
<bean id="transactionDao" class="org.mengyun.tcctransaction.server.dao.JdbcTransactionDao"/>
複製代碼
tccDomain
,項目訪問根目錄。配置方式以下:
// tcc-transaction-server.properties
tcc_domain=
複製代碼
調用 TransactionController#manager(...)
方法,查看事務列表。實現代碼以下:
@RequestMapping(value = "/management", method = RequestMethod.GET)
public ModelAndView manager() {
return new ModelAndView("manager");
}
@RequestMapping(value = "/management/domain/{domain}", method = RequestMethod.GET)
public ModelAndView manager(@PathVariable String domain) {
return manager(domain, DEFAULT_PAGE_NUM);
}
@RequestMapping(value = "/management/domain/{domain}/pagenum/{pageNum}", method = RequestMethod.GET)
public ModelAndView manager(@PathVariable String domain, @PathVariable Integer pageNum) {
ModelAndView modelAndView = new ModelAndView("manager");
// 得到事務 VO 數組
List<TransactionVo> transactionVos = transactionDao.findTransactions(domain, pageNum, DEFAULT_PAGE_SIZE);
// 得到事務總數量
Integer totalCount = transactionDao.countOfFindTransactions(domain);
// 計算總頁數
Integer pages = totalCount / DEFAULT_PAGE_SIZE;
if (totalCount % DEFAULT_PAGE_SIZE > 0) {
pages++;
}
// 返回
modelAndView.addObject("transactionVos", transactionVos);
modelAndView.addObject("pageNum", pageNum);
modelAndView.addObject("pageSize", DEFAULT_PAGE_SIZE);
modelAndView.addObject("pages", pages);
modelAndView.addObject("domain", domain);
modelAndView.addObject("urlWithoutPaging", tccDomain + "/management/domain/" + domain);
return modelAndView;
}
複製代碼
UI 界面以下:
調用 TransactionController#reset(...)
方法,事務重置重試次數。實現代碼以下:
@RequestMapping(value = "/domain/{domain}/retry/reset", method = RequestMethod.PUT)
@ResponseBody
public CommonResponse<Void> reset(@PathVariable String domain, String globalTxId, String branchQualifier) {
transactionDao.resetRetryCount(domain,
DatatypeConverter.parseHexBinary(globalTxId),
DatatypeConverter.parseHexBinary(branchQualifier));
return new CommonResponse<Void>();
}
複製代碼
UI 界面以下:
可能有人會吐槽運維平臺怎麼作的這麼簡陋。這個不是 TCC-Transaction 一個開源項目存在的問題,其餘例如 Dubbo、Disconf 等等都會存在這個狀況。
開源做者由於時間關係,更多的精力關注在覈心代碼,因此對運維友好性可能花費的精力較少。
固然,由於是開源的關係,咱們能夠本身作運維平臺反向的貢獻到這些項目。
胖友,分享一個朋友圈可好?