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

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