無標題文章1

title: TCC-Transaction 源碼分析 —— 事務(wù)存儲器

date: 2018-02-15

tags:

categories: TCC-Transaction

permalink: TCC-Transaction/transaction-repository

---

摘要: 原創(chuàng)出處 http://www.iocoder.cn/TCC-Transaction/transaction-repository/ 「芋道源碼」歡迎轉(zhuǎn)載戚啥,保留摘要,謝謝!

**本文主要基于 TCC-Transaction 1.2.3.3 正式版**

-[1. 概述](http://www.iocoder.cn/TCC-Transaction/transaction-repository/)

-[2. 序列化](http://www.iocoder.cn/TCC-Transaction/transaction-repository/)

-[2.1 JDK 序列化實現(xiàn)](http://www.iocoder.cn/TCC-Transaction/transaction-repository/)

-[2.2 Kyro 序列化實現(xiàn)](http://www.iocoder.cn/TCC-Transaction/transaction-repository/)

-[2.3 JSON 序列化實現(xiàn)](http://www.iocoder.cn/TCC-Transaction/transaction-repository/)

-[3. 存儲器](http://www.iocoder.cn/TCC-Transaction/transaction-repository/)

-[3.1 可緩存的事務(wù)存儲器抽象類](http://www.iocoder.cn/TCC-Transaction/transaction-repository/)

-[3.2 JDBC 事務(wù)存儲器](http://www.iocoder.cn/TCC-Transaction/transaction-repository/)

-[3.3 Redis 事務(wù)存儲器](http://www.iocoder.cn/TCC-Transaction/transaction-repository/)

-[3.4 Zookeeper 事務(wù)存儲器](http://www.iocoder.cn/TCC-Transaction/transaction-repository/)

-[3.5 File 事務(wù)存儲器](http://www.iocoder.cn/TCC-Transaction/transaction-repository/)

-[666. 彩蛋](http://www.iocoder.cn/TCC-Transaction/transaction-repository/)

-------

![](http://www.iocoder.cn/images/common/wechat_mp_2017_07_31.jpg)

>??????關(guān)注**微信公眾號:【芋道源碼】**有福利:

>1.RocketMQ / MyCAT / Sharding-JDBC **所有**源碼分析文章列表

>2.RocketMQ / MyCAT / Sharding-JDBC **中文注釋源碼 GitHub 地址**

>3.您對于源碼的疑問每條留言**都**將得到**認真**回復(fù)。**甚至不知道如何讀源碼也可以請教噢**。

>4.**新的**源碼解析文章**實時**收到通知。**每周更新一篇左右**。

>5.**認真的**源碼交流微信群簇爆。

---

# 1. 概述

本文分享**事務(wù)存儲器**。主要涉及如下 Maven 項目:

*`tcc-transaction-core`:tcc-transaction 底層實現(xiàn)倾贰。

在 TCC 的過程中冕碟,根據(jù)應(yīng)用內(nèi)存中的事務(wù)信息完成整個事務(wù)流程。But 實際業(yè)務(wù)場景中匆浙,將事務(wù)信息只放在應(yīng)用內(nèi)存中是遠遠不夠可靠的安寺。例如:

1.應(yīng)用進程異常崩潰,未完成的事務(wù)信息將丟失首尼。

2.應(yīng)用進程集群挑庶,當提供遠程服務(wù)調(diào)用時,事務(wù)信息需要集群內(nèi)共享软能。

3.發(fā)起事務(wù)的應(yīng)用需要重啟部署新版本迎捺,因為各種原因,有未完成的事務(wù)查排。

因此凳枝,TCC-Transaction 將事務(wù)信息添加到內(nèi)存中的同時,會使用外部存儲進行持久化。目前提供四種外部存儲:

*JdbcTransactionRepository岖瑰,JDBC 事務(wù)存儲器

*RedisTransactionRepository叛买,Redis 事務(wù)存儲器

*ZooKeeperTransactionRepository,Zookeeper 事務(wù)存儲器

*FileSystemTransactionRepository蹋订,F(xiàn)ile 事務(wù)存儲器

本文涉及到的類關(guān)系如下圖([打開大圖](http://www.iocoder.cn/images/TCC-Transaction/2018_02_15/01.png) ):

![](http://www.iocoder.cn/images/TCC-Transaction/2018_02_15/01.png)

>你行好事會因為得到贊賞而愉悅

>同理率挣,開源項目貢獻者會因為 Star 而更加有動力

>為 TCC-Transaction 點贊![傳送門](https://github.com/changmingxie/tcc-transaction)

ps:筆者假設(shè)你已經(jīng)閱讀過[《tcc-transaction 官方文檔 —— 使用指南1.2.x》](https://github.com/changmingxie/tcc-transaction/wiki/%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%971.2.x)露戒。

# 2. 序列化

在[《TCC-Transaction 源碼分析 —— TCC 實現(xiàn)》「4. 事務(wù)與參與者」](http://www.iocoder.cn/TCC-Transaction/tcc-core/?self)椒功,可以看到 Transaction 是一個比較復(fù)雜的對象,內(nèi)嵌 Participant 數(shù)組智什,而 Participant 本身也是復(fù)雜的對象动漾,內(nèi)嵌了更多的其他對象,因此荠锭,存儲器在持久化 Transaction 時谦炬,需要序列化后才能存儲。

`org.mengyun.tcctransaction.serializer.ObjectSerializer`节沦,對象序列化**接口**。實現(xiàn)代碼如下:

```Java

public interface ObjectSerializer {

byte[] serialize(T t);

T deserialize(byte[] bytes);

}

```

目前提供**JDK自帶序列化**和**Kyro序列化**兩種實現(xiàn)础爬。

## 2.1 JDK 序列化實現(xiàn)

`org.mengyun.tcctransaction.serializer.JdkSerializationSerializer`甫贯,JDK 序列化實現(xiàn)。比較易懂看蚜,點擊[鏈接](https://github.com/changmingxie/tcc-transaction/blob/70130d12004456fd4b97510c210c24502a1b3acb/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/serializer/JdkSerializationSerializer.java)直接查看叫搁。

**TCC-Transaction 使用的默認的序列化**。

## 2.2 Kyro 序列化實現(xiàn)

`org.mengyun.tcctransaction.serializer.KryoTransactionSerializer`供炎,Kyro 序列化實現(xiàn)渴逻。比較易懂,點擊[鏈接](https://github.com/changmingxie/tcc-transaction/blob/70130d12004456fd4b97510c210c24502a1b3acb/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/serializer/KryoTransactionSerializer.java)直接查看音诫。

## 2.3 JSON 序列化實現(xiàn)

JDK 和 Kyro 的序列化實現(xiàn)惨奕,肉眼無法直觀具體存儲事務(wù)的信息,你可以通過實現(xiàn) ObjectSerializer 接口竭钝,實現(xiàn)自定義的 JSON 序列化梨撞。

# 3. 存儲器

`org.mengyun.tcctransaction.TransactionRepository`,事務(wù)存儲器**接口**香罐。實現(xiàn)代碼如下:

```Java

public interface TransactionRepository {

/**

* 新增事務(wù)

*

* @paramtransaction事務(wù)

* @return 新增數(shù)量

*/

int create(Transaction transaction);

/**

* 更新事務(wù)

*

* @paramtransaction事務(wù)

* @return 更新數(shù)量

*/

int update(Transaction transaction);

/**

* 刪除事務(wù)

*

* @paramtransaction事務(wù)

* @return 刪除數(shù)量

*/

int delete(Transaction transaction);

/**

* 獲取事務(wù)

*

* @paramxid事務(wù)編號

* @return 事務(wù)

*/

Transaction findByXid(TransactionXid xid);

/**

* 獲取超過指定時間的事務(wù)集合

*

* @paramdate指定時間

* @return 事務(wù)集合

*/

List findAllUnmodifiedSince(Date date);

}

```

不同的存儲器通過實現(xiàn)該接口卧波,提供事務(wù)的增刪改查功能。

## 3.1 可緩存的事務(wù)存儲器抽象類

`org.mengyun.tcctransaction.repository.CachableTransactionRepository`庇茫,**可緩存**的事務(wù)存儲器**抽象類**港粱,實現(xiàn)增刪改查事務(wù)時,同時緩存事務(wù)信息旦签。在上面類圖查坪,我們也可以看到 TCC-Transaction 自帶的多種存儲器都繼承該抽象類寸宏。

**CachableTransactionRepository 構(gòu)造方法**實現(xiàn)代碼如下:

```Java

public abstract class CachableTransactionRepository implements TransactionRepository {

/**

* 緩存過期時間

*/

private int expireDuration = 120;

/**

* 緩存

*/

private Cache transactionXidCompensableTransactionCache;

public CachableTransactionRepository() {

transactionXidCompensableTransactionCache = CacheBuilder.newBuilder().expireAfterAccess(expireDuration, TimeUnit.SECONDS).maximumSize(1000).build();

}

}

```

*使用[Guava Cache](https://github.com/google/guava/wiki/CachesExplained) 內(nèi)存緩存事務(wù)信息,設(shè)置最大緩存?zhèn)€數(shù)為 1000 個咪惠,緩存過期時間為最后訪問時間 120 秒击吱。

-------

**`#create(...)`**實現(xiàn)代碼如下:

```Java

@Override

public int create(Transaction transaction) {

int result = doCreate(transaction);

if (result > 0) {

putToCache(transaction);

}

return result;

}

/**

* 添加到緩存

*

* @paramtransaction事務(wù)

*/

protected void putToCache(Transaction transaction) {

transactionXidCompensableTransactionCache.put(transaction.getXid(), transaction);

}

/**

* 新增事務(wù)

*

* @paramtransaction事務(wù)

* @return 新增數(shù)量

*/

protected abstract int doCreate(Transaction transaction);

```

*調(diào)用`#doCreate(...)`方法,新增事務(wù)遥昧。新增成功后覆醇,調(diào)用`#putToCache(...)`方法,添加事務(wù)到緩存炭臭。

*`#doCreate(...)`為抽象方法永脓,子類實現(xiàn)該方法,提供新增事務(wù)功能鞋仍。

-------

**`#update(...)`**實現(xiàn)代碼如下:

```Java

@Override

public int update(Transaction transaction) {

int result = 0;

try {

result = doUpdate(transaction);

if (result > 0) {

putToCache(transaction);

} else {

throw new OptimisticLockException();

}

} finally {

if (result <= 0) { // 更新失敗常摧,移除緩存。下次訪問威创,從存儲器讀取

removeFromCache(transaction);

}

}

return result;

}

/**

* 移除事務(wù)從緩存

*

* @paramtransaction事務(wù)

*/

protected void removeFromCache(Transaction transaction) {

transactionXidCompensableTransactionCache.invalidate(transaction.getXid());

}

/**

* 更新事務(wù)

*

* @paramtransaction事務(wù)

* @return 更新數(shù)量

*/

protected abstract int doUpdate(Transaction transaction);

```

*調(diào)用`#doUpdate(...)`方法落午,更新事務(wù)。

*若更新成功后肚豺,調(diào)用`#putToCache(...)`方法溃斋,添加事務(wù)到緩存。

*若更新失敗后吸申,拋出 OptimisticLockException 異常梗劫。有兩種情況會導(dǎo)致更新失敗:(1) 該事務(wù)已經(jīng)被提交截碴,被刪除梳侨;(2) 樂觀鎖更新時,緩存的事務(wù)的版本號(`Transaction.version`)和存儲器里的事務(wù)的版本號不同日丹,更新失敗走哺。**為什么**?在[《TCC-Transaction 源碼分析 —— 事務(wù)恢復(fù)》](http://www.iocoder.cn/TCC-Transaction/transaction-recovery/)詳細解析哲虾。更新失敗割坠,意味著緩存已經(jīng)不不一致,調(diào)用`#removeFromCache(...)`方法妒牙,移除事務(wù)從緩存中彼哼。

*`#doUpdate(...)`為抽象方法,子類實現(xiàn)該方法湘今,提供更新事務(wù)功能敢朱。

-------

**`#delete(...)`**實現(xiàn)代碼如下:

```Java

@Override

public int delete(Transaction transaction) {

int result;

try {

result = doDelete(transaction);

} finally {

removeFromCache(transaction);

}

return result;

}

/**

* 刪除事務(wù)

*

* @paramtransaction事務(wù)

* @return 刪除數(shù)量

*/

protected abstract int doDelete(Transaction transaction);

```

*調(diào)用`#doDelete(...)`方法,刪除事務(wù)。

*調(diào)用`#removeFromCache(...)`方法拴签,移除事務(wù)從緩存中孝常。

*`#doDelete(...)`為抽象方法,子類實現(xiàn)該方法蚓哩,提供刪除事務(wù)功能构灸。

-------

**`#findByXid(...)`**實現(xiàn)代碼如下:

```Java

@Override

public Transaction findByXid(TransactionXid transactionXid) {

Transaction transaction = findFromCache(transactionXid);

if (transaction == null) {

transaction = doFindOne(transactionXid);

if (transaction != null) {

putToCache(transaction);

}

}

return transaction;

}

/**

* 獲得事務(wù)從緩存中

*

* @paramtransactionXid事務(wù)編號

* @return 事務(wù)

*/

protected Transaction findFromCache(TransactionXid transactionXid) {

return transactionXidCompensableTransactionCache.getIfPresent(transactionXid);

}

/**

* 查詢事務(wù)

*

* @paramxid事務(wù)編號

* @return 事務(wù)

*/

protected abstract Transaction doFindOne(Xid xid);

```

*調(diào)用`#findFromCache()`方法,優(yōu)先從緩存中獲取事務(wù)岸梨。

*調(diào)用`#doFindOne()`方法喜颁,緩存中事務(wù)不存在,從存儲器中獲取曹阔。獲取到后半开,調(diào)用`#putToCache()`方法,添加事務(wù)到緩存中赃份。

*`#doFindOne(...)`為抽象方法寂拆,子類實現(xiàn)該方法,提供查詢事務(wù)功能抓韩。

-------

**`#findAllUnmodifiedSince(...)`**實現(xiàn)代碼如下:

```Java

@Override

public List findAllUnmodifiedSince(Date date) {

List transactions = doFindAllUnmodifiedSince(date);

// 添加到緩存

for (Transaction transaction : transactions) {

putToCache(transaction);

}

return transactions;

}

/**

* 獲取超過指定時間的事務(wù)集合

*

* @paramdate指定時間

* @return 事務(wù)集合

*/

protected abstract List doFindAllUnmodifiedSince(Date date);

```

*調(diào)用`#findAllUnmodifiedSince(...)`方法纠永,從存儲器獲取超過指定時間的事務(wù)集合。調(diào)用`#putToCache(...)`方法谒拴,循環(huán)事務(wù)集合添加到緩存渺蒿。

*`#doFindAllUnmodifiedSince(...)`為抽象方法,子類實現(xiàn)該方法彪薛,提供獲取超過指定時間的事務(wù)集合功能。

## 3.2 JDBC 事務(wù)存儲器

`org.mengyun.tcctransaction.repository.JdbcTransactionRepository`怠蹂,JDBC 事務(wù)存儲器善延,通過 JDBC 驅(qū)動,將 Transaction 存儲到 MySQL / Oracle / PostgreSQL / SQLServer 等關(guān)系數(shù)據(jù)庫城侧。實現(xiàn)代碼如下:

```Java

public class JdbcTransactionRepository extends CachableTransactionRepository {

/**

* 領(lǐng)域

*/

private String domain;

/**

* 表后綴

*/

private String tbSuffix;

/**

* 數(shù)據(jù)源

*/

private DataSource dataSource;

/**

* 序列化

*/

private ObjectSerializer serializer = new JdkSerializationSerializer();

}

```

*`domain`易遣,領(lǐng)域,或者也可以稱為模塊名嫌佑,應(yīng)用名豆茫,**用于唯一標識一個資源**。例如屋摇,Maven 模塊`xxx-order`揩魂,我們可以配置該屬性為`ORDER`。

*`tbSuffix`炮温,表后綴火脉。默認存儲表名為`TCC_TRANSACTION`,配置表名后,為`TCC_TRANSACTION${tbSuffix}`倦挂。

*`dataSource`畸颅,存儲數(shù)據(jù)的數(shù)據(jù)源。

*`serializer`方援,序列化没炒。**當數(shù)據(jù)庫里已經(jīng)有數(shù)據(jù)的情況下,不要更換別的序列化犯戏,否則會導(dǎo)致反序列化報錯送火。**建議:TCC-Transaction 存儲時,新增字段笛丙,記錄序列化的方式漾脂。

表結(jié)構(gòu)如下:

```Java

CREATE TABLE `TCC_TRANSACTION` (

`TRANSACTION_ID` int(11) NOT NULL AUTO_INCREMENT,

`DOMAIN` varchar(100) DEFAULT NULL,

`GLOBAL_TX_ID` varbinary(32) NOT NULL,

`BRANCH_QUALIFIER` varbinary(32) NOT NULL,

`CONTENT` varbinary(8000) DEFAULT NULL,

`STATUS` int(11) DEFAULT NULL,

`TRANSACTION_TYPE` int(11) DEFAULT NULL,

`RETRIED_COUNT` int(11) DEFAULT NULL,

`CREATE_TIME` datetime DEFAULT NULL,

`LAST_UPDATE_TIME` datetime DEFAULT NULL,

`VERSION` int(11) DEFAULT NULL,

PRIMARY KEY (`TRANSACTION_ID`),

UNIQUE KEY `UX_TX_BQ` (`GLOBAL_TX_ID`,`BRANCH_QUALIFIER`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8

```

*`TRANSACTION_ID`,僅僅數(shù)據(jù)庫自增胚鸯,無實際用途骨稿。

*`CONTENT`,Transaction 序列化姜钳。

ps:點擊[鏈接](https://github.com/YunaiV/tcc-transaction/blob/c164ff5ab29d31e08bc7061de5bc7403f3e40f1d/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/repository/JdbcTransactionRepository.java)查看 JdbcTransactionRepository 代碼實現(xiàn)坦冠,已經(jīng)添加完整中文注釋。

## 3.3 Redis 事務(wù)存儲器

`org.mengyun.tcctransaction.repository.RedisTransactionRepository`哥桥,Redis 事務(wù)存儲器辙浑,將 Transaction 存儲到 Redis。實現(xiàn)代碼如下:

```Java

public class RedisTransactionRepository extends CachableTransactionRepository {

/**

* Jedis Pool

*/

private JedisPool jedisPool;

/**

* key 前綴

*/

private String keyPrefix = "TCC:";

/**

* 序列化

*/

private ObjectSerializer serializer = new JdkSerializationSerializer();

}

```

*`keyPrefix`拟糕,key 前綴判呕。類似 JdbcTransactionRepository 的`domain`屬性。

一個事務(wù)存儲到 Reids送滞,使用 Redis 的數(shù)據(jù)結(jié)構(gòu)為[HASHES](https://redis.io/commands#hash)侠草。

*key : 使用`keyPrefix`+`xid`,實現(xiàn)代碼如下:

```Java

/**

* 創(chuàng)建事務(wù)的 Redis Key

*

* @paramkeyPrefixkey 前綴

* @paramxid事務(wù)

* @return Redis Key

*/

public static byte[] getRedisKey(String keyPrefix, Xid xid) {

byte[] prefix = keyPrefix.getBytes();

byte[] globalTransactionId = xid.getGlobalTransactionId();

byte[] branchQualifier = xid.getBranchQualifier();

// 拼接 key

byte[] key = new byte[prefix.length + globalTransactionId.length + branchQualifier.length];

System.arraycopy(prefix, 0, key, 0, prefix.length);

System.arraycopy(globalTransactionId, 0, key, prefix.length, globalTransactionId.length);

System.arraycopy(branchQualifier, 0, key, prefix.length + globalTransactionId.length, branchQualifier.length);

return key;

}

```

*HASHES 的 key :使用`version`犁嗅。

*添加和更新 Transaction 時边涕,使用 Redis[HSETNX](https://redis.io/commands/hsetnx),不存在當前版本的值時褂微,進行設(shè)置功蜓,重而實現(xiàn)類似樂觀鎖的更新。

*讀取 Transaction 時式撼,使用 Redis[HGETALL](https://redis.io/commands/hgetall),將 Transaction 所有`version`對應(yīng)的值讀取到內(nèi)存后求厕,取`version`值最大的對應(yīng)的值端衰。

*HASHES 的 value :調(diào)用`TransactionSerializer#serialize(...)`方法叠洗,序列化 Transaction。實現(xiàn)代碼如下:

```Java

public static byte[] serialize(ObjectSerializer serializer, Transaction transaction) {

Map map = new HashMap();

map.put("GLOBAL_TX_ID", transaction.getXid().getGlobalTransactionId());

map.put("BRANCH_QUALIFIER", transaction.getXid().getBranchQualifier());

map.put("STATUS", transaction.getStatus().getId());

map.put("TRANSACTION_TYPE", transaction.getTransactionType().getId());

map.put("RETRIED_COUNT", transaction.getRetriedCount());

map.put("CREATE_TIME", transaction.getCreateTime());

map.put("LAST_UPDATE_TIME", transaction.getLastUpdateTime());

map.put("VERSION", transaction.getVersion());

// 序列化

map.put("CONTENT", serializer.serialize(transaction));

return serializer.serialize(map);

}

```

*TODO 為什么序列化兩次

在實現(xiàn)`#doFindAllUnmodifiedSince(date)`方法旅东,無法像數(shù)據(jù)庫使用時間條件進行過濾灭抑,因此,加載所有事務(wù)后在內(nèi)存中過濾抵代。實現(xiàn)代碼如下:

```Java

@Override

protected List doFindAllUnmodifiedSince(Date date) {

// 獲得所有事務(wù)

List allTransactions = doFindAll();

// 過濾時間

List allUnmodifiedSince = new ArrayList();

for (Transaction transaction : allTransactions) {

if (transaction.getLastUpdateTime().compareTo(date) < 0) {

allUnmodifiedSince.add(transaction);

}

}

return allUnmodifiedSince;

}

```

ps:點擊[鏈接](https://github.com/YunaiV/tcc-transaction/blob/c164ff5ab29d31e08bc7061de5bc7403f3e40f1d/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/repository/RedisTransactionRepository.java)查看 RedisTransactionRepository 代碼實現(xiàn)腾节,已經(jīng)添加完整中文注釋。

>FROM [《TCC-Transaction 官方文檔 —— 使用指南1.2.x》](https://github.com/changmingxie/tcc-transaction/wiki/%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%971.2.x#%E9%85%8D%E7%BD%AEtcc-transaction)

>使用 RedisTransactionRepository 需要配置 Redis 服務(wù)器如下:

>appendonly yes

>appendfsync always

## 3.4 Zookeeper 事務(wù)存儲器

`org.mengyun.tcctransaction.repository.ZooKeeperTransactionRepository`荤牍,Zookeeper 事務(wù)存儲器案腺,將 Transaction 存儲到 Zookeeper。實現(xiàn)代碼如下:

```Java

public class ZooKeeperTransactionRepository extends CachableTransactionRepository {

/**

* Zookeeper 服務(wù)器地址數(shù)組

*/

private String zkServers;

/**

* Zookeeper 超時時間

*/

private int zkTimeout;

/**

* TCC 存儲 Zookeeper 根目錄

*/

private String zkRootPath = "/tcc";

/**

* Zookeeper 連接

*/

private volatile ZooKeeper zk;

/**

* 序列化

*/

private ObjectSerializer serializer = new JdkSerializationSerializer();

}

```

*`zkRootPath`康吵,存儲 Zookeeper 根目錄劈榨,類似 JdbcTransactionRepository 的`domain`屬性。

一個事務(wù)存儲到 Zookeeper晦嵌,使用 Zookeeper 的**持久數(shù)據(jù)節(jié)點**同辣。

*path:`${zkRootPath}`+`/`+`${xid}`。實現(xiàn)代碼如下:

```Java

// ZooKeeperTransactionRepository.java

private String getTxidPath(Xid xid) {

return String.format("%s/%s", zkRootPath, xid);

}

// TransactionXid.java

@Override

public String toString() {

StringBuilder stringBuilder = new StringBuilder();

stringBuilder.append("globalTransactionId:").append(UUID.nameUUIDFromBytes(globalTransactionId).toString());

stringBuilder.append(",").append("branchQualifier:").append(UUID.nameUUIDFromBytes(branchQualifier).toString());

return stringBuilder.toString();

}

```

*data:調(diào)用`TransactionSerializer#serialize(...)`方法惭载,序列化 Transaction旱函。

*version:使用 Zookeeper 數(shù)據(jù)節(jié)點自帶版本功能。這里要注意下描滔,Transaction 的版本從 1 開始棒妨,而 Zookeeper 數(shù)據(jù)節(jié)點版本從 0 開始。

ps:點擊[鏈接](https://github.com/YunaiV/tcc-transaction/blob/c164ff5ab29d31e08bc7061de5bc7403f3e40f1d/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/repository/ZooKeeperTransactionRepository.java)查看 ZooKeeperTransactionRepository 代碼實現(xiàn)含长,已經(jīng)添加完整中文注釋券腔。

另外,在生產(chǎn)上暫時不建議使用 ZooKeeperTransactionRepository拘泞,原因有兩點:

*不支持 Zookeeper 安全認證纷纫。

*使用 Zookeeper 時,未考慮斷網(wǎng)重連等情況田弥。

如果你要使用 Zookeeper 進行事務(wù)的存儲,可以考慮使用[Apache Curator](https://curator.apache.org/) 操作 Zookeeper铡原,重寫 ZooKeeperTransactionRepository 部分代碼偷厦。

## 3.5 File 事務(wù)存儲器

`org.mengyun.tcctransaction.repository.FileSystemTransactionRepository`,F(xiàn)ile 事務(wù)存儲器燕刻,將 Transaction 存儲到文件系統(tǒng)只泼。

實現(xiàn)上和 ZooKeeperTransactionRepository,區(qū)別主要在于不支持樂觀鎖更新卵洗。有興趣的同學(xué)點擊[鏈接](https://github.com/YunaiV/tcc-transaction/blob/c164ff5ab29d31e08bc7061de5bc7403f3e40f1d/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/repository/FileSystemTransactionRepository.java)查看请唱,這里就不拓展開來弥咪。

另外,在生產(chǎn)上不建議使用 FileSystemTransactionRepository十绑,因為不支持多節(jié)點共享聚至。用分布式存儲掛載文件另說,當然還是不建議本橙,因為不支持樂觀鎖并發(fā)更新扳躬。

# 666. 彩蛋

這篇略( 超 )微( 級 )水更,哈哈哈甚亭,為[《TCC-Transaction 源碼分析 —— 事務(wù)恢復(fù)》](http://www.iocoder.cn/TCC-Transaction/transaction-recover/?self)做鋪墊啦贷币。

使用 RedisTransactionRepository 和 ZooKeeperTransactionRepository 存儲事務(wù)還是 Get 蠻多點的。

![](http://www.iocoder.cn/images/TCC-Transaction/2018_02_15/02.png)

胖友亏狰,分享一個朋友圈可好役纹?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市暇唾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌信不,老刑警劉巖嘲叔,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異抽活,居然都是意外死亡硫戈,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門下硕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丁逝,“玉大人,你說我怎么就攤上這事梭姓∷祝” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵誉尖,是天一觀的道長罪既。 經(jīng)常有香客問我,道長铡恕,這世上最難降的妖魔是什么琢感? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮探熔,結(jié)果婚禮上驹针,老公的妹妹穿的比我還像新娘。我一直安慰自己诀艰,他們只是感情好柬甥,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布饮六。 她就那樣靜靜地躺著,像睡著了一般苛蒲。 火紅的嫁衣襯著肌膚如雪卤橄。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天撤防,我揣著相機與錄音虽风,去河邊找鬼。 笑死寄月,一個胖子當著我的面吹牛辜膝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播漾肮,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼厂抖,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了克懊?” 一聲冷哼從身側(cè)響起忱辅,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谭溉,沒想到半個月后墙懂,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡扮念,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年损搬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柜与。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡巧勤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出弄匕,到底是詐尸還是另有隱情颅悉,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布迁匠,位于F島的核電站剩瓶,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏城丧。R本人自食惡果不足惜延曙,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望芙贫。 院中可真熱鬧搂鲫,春花似錦傍药、人聲如沸磺平。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拣挪。三九已至擦酌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間菠劝,已是汗流浹背赊舶。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留赶诊,地道東北人笼平。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像舔痪,于是被迫代替她去往敵國和親寓调。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 首 通道頭2通道尾 版本頭2.2版本尾 更新內(nèi)容頭優(yōu)化軟件锄码,更新內(nèi)容尾 購卡地址頭http://www.baidu...
    百度_78da閱讀 253評論 0 0
  • 無標題文章1無標題文章1無標題文章1無標題文章1無標題文章1無標題文章1無標題文章1無標題文章1無標題文章1無標題...
    心似羽毛閱讀 148評論 0 0
  • 說到今日頭條我算是比較晚入駐的一批,入駐今日頭條我做的第一件事情就是把今日頭條所有的官方公告都看了一遍(里面有價值...
    李聰榮閱讀 678評論 1 1
  • 2017年7月7日重窟,這個日期看似有特別之處载萌,其實生活還是一往如常,星期五亲族,準備回家看一看炒考,所以用打車軟...
    老古董Felix閱讀 280評論 0 1
  • [TOC] 字典集合 字典:字典(存放鍵值對組合的容器)字典中的每個元素都是由兩部分構(gòu)成的, 冒號前面是鍵冒號后面...
    檜霖閱讀 546評論 1 7