跨數(shù)據(jù)庫(kù)的事務(wù),只能在業(yè)務(wù)上保證。
不能保證的是,2個(gè)SQL能夠在同一時(shí)間成功。
業(yè)務(wù)上的先期檢查、校驗(yàn)、分布式鎖的設(shè)計(jì),再加上一部分的措施(不停重試、先劃一部分蛋糕再恢復(fù))是必須要考慮的問(wèn)題和方案。
http://dangdangdotcom.github.io/sharding-jdbc/post/soft_transaction/
http://dangdangdotcom.github.io/sharding-jdbc/post/transaction/
最大努力送達(dá)型
概念
在分布式數(shù)據(jù)庫(kù)的場(chǎng)景下,相信對(duì)于該數(shù)據(jù)庫(kù)的操作最終一定可以成功,所以通過(guò)最大努力反復(fù)嘗試送達(dá)操作。
架構(gòu)圖

適用場(chǎng)景
- 根據(jù)主鍵刪除數(shù)據(jù)。
- 更新記錄永久狀態(tài),如更新通知送達(dá)狀態(tài)。
使用限制
使用最大努力送達(dá)型柔性事務(wù)的SQL
需要滿足冪等性。
- INSERT語(yǔ)句要求必須包含主鍵,且不能是自增主鍵。
- UPDATE語(yǔ)句要求冪等,不能是
UPDATE xxx SET x=x+1
- DELETE語(yǔ)句無(wú)要求。
開(kāi)發(fā)指南
Sharding-JDBC-transaction
完全基于java
開(kāi)發(fā),直接提供jar
包,可直接使用maven導(dǎo)入坐標(biāo)即可使用。- 為了保證事務(wù)不丟失,
Sharding-JDBC-transaction
需要提供數(shù)據(jù)庫(kù)存儲(chǔ)事務(wù)日志,配置方法可參見(jiàn)事務(wù)管理器配置項(xiàng)。 - 由于柔性事務(wù)采用異步嘗試,需要部署獨(dú)立的作業(yè)和
Zookeeper
。Sharding-JDBC-transaction
采用elastic-job
實(shí)現(xiàn)的Sharding-JDBC-transaction-async-job
,通過(guò)簡(jiǎn)單配置即可啟動(dòng)高可用作業(yè)異步送達(dá)柔性事務(wù),啟動(dòng)腳本為start.sh
。 - 為了便于開(kāi)發(fā),
Sharding-JDBC-transaction
提供了基于內(nèi)存的事務(wù)日志存儲(chǔ)器和內(nèi)嵌異步作業(yè)。
開(kāi)發(fā)示例
// 1. 配置SoftTransactionConfiguration SoftTransactionConfiguration transactionConfig = new SoftTransactionConfiguration(dataSource); transactionConfig.setXXX(); // 2. 初始化SoftTransactionManager SoftTransactionManager transactionManager = new SoftTransactionManager(transactionConfig); transactionManager.init(); // 3. 獲取BEDSoftTransaction BEDSoftTransaction transaction = (BEDSoftTransaction) transactionManager.getTransaction(SoftTransactionType.BestEffortsDelivery); // 4. 開(kāi)啟事務(wù) transaction.begin(connection); // 5. 執(zhí)行JDBC /* codes here */ * // 6.關(guān)閉事務(wù) transaction.end();
事務(wù)管理器配置項(xiàng)
SoftTransactionConfiguration
配置
用于配置事務(wù)管理器。
名稱(chēng) | 類(lèi)型 | 必填 | 默認(rèn)值 | 說(shuō)明 |
---|
shardingDataSource | ShardingDataSource | 是 | | 事務(wù)管理器管理的數(shù)據(jù)源 |
syncMaxDeliveryTryTimes | int | 否 | 3 | 同步的事務(wù)送達(dá)的最大嘗試次數(shù) |
storageType | enum | 否 | RDB | 事務(wù)日志存儲(chǔ)類(lèi)型。可選值: RDB,MEMORY。使用RDB類(lèi)型將自動(dòng)建表 |
transactionLogDataSource | DataSource | 否 | null | 存儲(chǔ)事務(wù)日志的數(shù)據(jù)源,如果storageType為RDB則必填 |
bestEffortsDeliveryJobConfiguration | NestedBestEffortsDeliveryJobConfiguration | 否 | null | 最大努力送達(dá)型內(nèi)嵌異步作業(yè)配置對(duì)象。如需使用,請(qǐng)參考NestedBestEffortsDeliveryJobConfiguration 配置 |
NestedBestEffortsDeliveryJobConfiguration
配置 (僅開(kāi)發(fā)環(huán)境)
用于配置內(nèi)嵌的異步作業(yè),僅用于開(kāi)發(fā)環(huán)境。生產(chǎn)環(huán)境應(yīng)使用獨(dú)立部署的作業(yè)版本。
名稱(chēng) | 類(lèi)型 | 必填 | 默認(rèn)值 | 說(shuō)明 |
---|
zookeeperPort | int | 否 | 4181 | 內(nèi)嵌的注冊(cè)中心端口號(hào) |
zookeeperDataDir | String | 否 | target/test_zk_data/nano/ | 內(nèi)嵌的注冊(cè)中心的數(shù)據(jù)存放目錄 |
asyncMaxDeliveryTryTimes | int | 否 | 3 | 異步的事務(wù)送達(dá)的最大嘗試次數(shù) |
asyncMaxDeliveryTryDelayMillis | long | 否 | 60000 | 執(zhí)行異步送達(dá)事務(wù)的延遲毫秒數(shù),早于此間隔時(shí)間的入庫(kù)事務(wù)才會(huì)被異步作業(yè)執(zhí)行 |
獨(dú)立部署作業(yè)指南
- 部署用于存儲(chǔ)事務(wù)日志的數(shù)據(jù)庫(kù)。
- 部署用于異步作業(yè)使用的
Zookeeper
。 - 配置
yaml
文件,參照示例。 - 下載并解壓文件
sharding-jdbc-transaction-async-job-$VERSION.tar
,通過(guò)start.sh
腳本啟動(dòng)異步作業(yè)。
異步作業(yè)yaml文件配置
#目標(biāo)數(shù)據(jù)庫(kù)的數(shù)據(jù)源. targetDataSource: ds_0: !!org.apache.commons.dbcp.BasicDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/ds_0 username: root password: ds_1: !!org.apache.commons.dbcp.BasicDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/ds_1 username: root password: #事務(wù)日志的數(shù)據(jù)源. transactionLogDataSource: ds_trans: !!org.apache.commons.dbcp.BasicDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/trans_log username: root password: #注冊(cè)中心配置 zkConfig: #注冊(cè)中心的連接地址 connectionString: localhost:2181 #作業(yè)的命名空間 namespace: Best-Efforts-Delivery-Job #注冊(cè)中心的等待重試的間隔時(shí)間的初始值 baseSleepTimeMilliseconds: 1000 #注冊(cè)中心的等待重試的間隔時(shí)間的最大值 maxSleepTimeMilliseconds: 3000 #注冊(cè)中心的最大重試次數(shù) maxRetries: 3 #作業(yè)配置 jobConfig: #作業(yè)名稱(chēng) name: bestEffortsDeliveryJob #觸發(fā)作業(yè)的cron表達(dá)式 cron: 0/5 * * * * ? #每次作業(yè)獲取的事務(wù)日志最大數(shù)量 transactionLogFetchDataCount: 100 #事務(wù)送達(dá)的最大嘗試次數(shù). maxDeliveryTryTimes: 3 #執(zhí)行送達(dá)事務(wù)的延遲毫秒數(shù),早于此間隔時(shí)間的入庫(kù)事務(wù)才會(huì)被作業(yè)執(zhí)行 maxDeliveryTryDelayMillis: 60000
事務(wù)支持說(shuō)明
Sharding-JDBC
由于性能方面的考量,決定不支持強(qiáng)一致性
分布式事務(wù)。我們已明確規(guī)劃線路圖,未來(lái)會(huì)支持最終一致性的柔性事務(wù)。
目前最大努力送達(dá)型
柔性事務(wù)已開(kāi)發(fā)完成。
如果不使用柔性事務(wù),也會(huì)自動(dòng)包含弱XA
事務(wù)支持,有以下幾點(diǎn)說(shuō)明:
完全支持非跨庫(kù)事務(wù),例如:僅分表,或分庫(kù)但是路由的結(jié)果在單庫(kù)中。
完全支持因邏輯異常導(dǎo)致的跨庫(kù)事務(wù)。例如:同一事務(wù)中,跨兩個(gè)庫(kù)更新。更新完畢后,拋出空指針,則兩個(gè)庫(kù)的內(nèi)容都能回滾。
不支持因網(wǎng)絡(luò)、硬件異常導(dǎo)致的跨庫(kù)事務(wù)。例如:同一事務(wù)中,跨兩個(gè)庫(kù)更新,更新完畢后、未提交之前,第一個(gè)庫(kù)死機(jī),則只有第二個(gè)庫(kù)數(shù)據(jù)提交。