ShardingJDBC——分布式事務

一僧凤、如何理解分布式事務

在傳統(tǒng)的關系型數(shù)據(jù)庫中畜侦,事務是一個標準組件,幾乎所有成熟的關系型數(shù)據(jù)庫都提供了對本地事務的原生支持躯保。本地事務提供了 ACID 事務特性旋膳。基于本地事務途事,為了保證數(shù)據(jù)的一致性验懊,我們先開啟一個事務后,才可以執(zhí)行數(shù)據(jù)操作尸变,最后提交或回滾就可以了义图。更進一步,借助于 Spring 等集成化框架召烂,開發(fā)人員只需關注引起數(shù)據(jù)改變的業(yè)務即可碱工。

但在分布式環(huán)境下,事情就會變得比較復雜奏夫。假設系統(tǒng)中存在多個獨立的數(shù)據(jù)庫怕篷,為了確保數(shù)據(jù)在這些獨立的數(shù)據(jù)庫中保持一致,我們需要把這些數(shù)據(jù)庫納入同一個事務中桶蛔。這時本地事務就無能為力了匙头,我們需要使用分布式事務。

業(yè)界關于如何實現(xiàn)分布式事務也有一些通用的實現(xiàn)機制仔雷,例如支持兩階段提交的 XA 協(xié)議以及以 Saga 為代表的柔性事務蹂析。針對不同的實現(xiàn)機制,也存在一些供應商和開發(fā)工具碟婆。因為這些開發(fā)工具在使用方式上和實現(xiàn)原理上都有較大的差異性电抚,所以開發(fā)人員的一大訴求在于,希望能有一套統(tǒng)一的解決方案能夠屏蔽這些差異竖共。同時蝙叛,我們也希望這種解決方案能夠提供友好的系統(tǒng)集成性。

ShardingSphere 作為一款分布式數(shù)據(jù)庫中間件公给,勢必要考慮分布式事務的實現(xiàn)方案借帘。而在設計上,ShardingSphere 從一開始就充分考慮到了開發(fā)人員的這些訴求淌铐。

二肺然、ShardingJdbc 分布式事務

sharding-jdbc分布式事務支持:官網(wǎng)https://shardingsphere.apache.org/document/current/cn/features/transaction/

ShardingSphere 中的分布式事務

在 ShardingSphere 中,除本地事務之外腿准,還提供針對分布式事務的兩種實現(xiàn)方案际起,分別是 XA 事務和柔性事務。這點可以從事務類型枚舉值 TransactionType 中得到驗證:

public enum TransactionType {
    LOCAL, XA, BASE
}

1、本地事務

在不開啟任何分布式事務管理器的前提下街望,讓每個數(shù)據(jù)節(jié)點各自管理自己的事務校翔。 它們之間沒有協(xié)調以及通信的能力,也并不互相知曉其他數(shù)據(jù)節(jié)點事務的成功與否灾前。 本地事務在性能方面無任何損耗防症,但在強一致性以及最終一致性方面則力不從心。

2豫柬、兩階段提交:

XA協(xié)議最早的分布式事務模型是由 X/Open 國際聯(lián)盟提出的 X/Open Distributed Transaction Processing (DTP) 模型告希,簡稱 XA 協(xié)議。

基于XA協(xié)議實現(xiàn)的分布式事務對業(yè)務侵入很小烧给。 它最大的優(yōu)勢就是對使用方透明燕偶,用戶可以像使用本地事務一樣使用基于XA協(xié)議的分布式事務。 XA協(xié)議能夠嚴格保障事務 ACID 特性础嫡。

嚴格保障事務 ACID 特性是一把雙刃劍指么。 事務執(zhí)行在過程中需要將所需資源全部鎖定,它更加適用于執(zhí)行時間確定的短事務榴鼎。 對于長事務來說伯诬,整個事務進行期間對數(shù)據(jù)的獨占,將導致對熱點數(shù)據(jù)依賴的業(yè)務系統(tǒng)并發(fā)性能衰退明顯巫财。 因此盗似,在高并發(fā)的性能至上場景中,基于XA協(xié)議的分布式事務并不是最佳選擇平项。

3赫舒、柔性事務

如果將實現(xiàn)了 ACID 的事務要素的事務稱為剛性事務的話,那么基于 BASE 事務要素的事務則稱為柔性事務闽瓢。 BASE 是基本可用接癌、柔性狀態(tài)和最終一致性這三個要素的縮寫。

  • 基本可用(Basically Available):允許響應時間拉長扣讼,允許功能上的損失缺猛,允許降級頁面(系統(tǒng)繁忙,稍后重試等)椭符,即分布式系統(tǒng)在出現(xiàn)故障時荔燎,允許損失部分可用功能,保證核心功能可用销钝。如湖雹,電商網(wǎng)站交易付款出現(xiàn)問題了,商品依然可以正常瀏覽曙搬。

  • 柔性狀態(tài)(Soft state):是指允許系統(tǒng)中的數(shù)據(jù)存在中間狀態(tài),并認為該中間狀態(tài)的存在不會影響系統(tǒng)的整體可用性。如訂單的"支付中"纵装、“數(shù)據(jù)同步中”等狀態(tài)征讲,待數(shù)據(jù)最終一致后狀態(tài)改為“成功”狀態(tài)。

  • 最終一致性(Eventually consistent):本質就是需要保證最終數(shù)據(jù)能夠達到一致性橡娄,而不需要實時保證系統(tǒng)數(shù)據(jù)的強一致性诗箍。如訂單的"支付中"狀態(tài),最終會變?yōu)椤爸Ц冻晒Α被蛘?支付失敗"挽唉,使訂單狀態(tài)與實際交易結果達成一致滤祖,但需要一定時間的延遲、等待瓶籽。

在 ACID 事務中對隔離性的要求很高匠童,在事務執(zhí)行過程中,必須將所有的資源鎖定塑顺。 柔性事務的理念則是通過業(yè)務邏輯將互斥鎖操作從資源層面上移至業(yè)務層面汤求。通過放寬對強一致性要求,來換取系統(tǒng)吞吐量的提升严拒。

三扬绪、ShardingJdbc 分布式事務使用

3.1 不使用Spring

3.1.1 引入Maven依賴

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-core</artifactId>
    <version>${sharding-sphere.version}</version>
</dependency>

<!-- 使用XA事務時,需要引入此模塊 -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-transaction-xa-core</artifactId>
    <version>${shardingsphere.version}</version>
</dependency>

<!-- 使用BASE事務時裤唠,需要引入此模塊 -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-transaction-base-seata-at</artifactId>
    <version>${sharding-sphere.version}</version>
</dependency>

3.1.2 基于Java編碼方式使用分布式事務

TransactionTypeHolder.set(TransactionType.XA); // 支持TransactionType.LOCAL, TransactionType.XA, TransactionType.BASE
try (Connection connection = dataSource.getConnection()) { // dataSource的類型為ShardingDataSource
    connection.setAutoCommit(false);
    PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO t_order (user_id, status) VALUES (?, ?)");
    preparedStatement.setObject(1, i);
    preparedStatement.setObject(2, "init");
    preparedStatement.executeUpdate();
    connection.commit();
}

3.2 使用Spring-namespace

3.2.1 引入Maven依賴

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-namespace</artifactId>
    <version>${shardingsphere.version}</version>
</dependency>

<!-- 使用XA事務時挤牛,需要引入此模塊 -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-transaction-xa-core</artifactId>
    <version>${shardingsphere.version}</version>
</dependency>

<!-- 使用BASE事務時,需要引入此模塊 -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-transaction-base-seata-at</artifactId>
    <version>${sharding-sphere.version}</version>
</dependency>

3.2.2 配置spring-namespace的事務管理器

<!-- 進行ShardingDataSource的相關配置 -->
...

<!-- 開啟自動掃描@ShardingTransactionType注解种蘸,使用Spring原生的AOP在類和方法上進行增強 -->
<sharding:tx-type-annotation-driven />

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="shardingDataSource" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="shardingDataSource" />
</bean>
<tx:annotation-driven />

3.2.3 業(yè)務代碼中使用分布式事務

@Transactional
@ShardingTransactionType(TransactionType.XA)  // 支持TransactionType.LOCAL, TransactionType.XA, TransactionType.BASE
public void insert() {
    jdbcTemplate.execute("INSERT INTO t_order (user_id, status) VALUES (?, ?)", (PreparedStatementCallback<Object>) preparedStatement -> {
        preparedStatement.setObject(1, i);
        preparedStatement.setObject(2, "init");
        preparedStatement.executeUpdate();
    });
}

3.3 使用Spring-boot

3.3.1 引入Maven依賴

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>${shardingsphere.version}</version>
</dependency>

<!-- 使用XA事務時墓赴,需要引入此模塊 -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-transaction-xa-core</artifactId>
    <version>${shardingsphere.version}</version>
</dependency>

<!-- 使用BASE事務時,需要引入此模塊 -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-transaction-base-seata-at</artifactId>
    <version>${sharding-sphere.version}</version>
</dependency>

3.3.2 配置spring-boot的事務管理器

@Configuration
@EnableTransactionManagement
public class TransactionConfiguration {
    
    @Bean
    public PlatformTransactionManager txManager(final DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
    
    @Bean
    public JdbcTemplate jdbcTemplate(final DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

3.3.3 業(yè)務代碼中使用分布式事務

@Transactional
@ShardingTransactionType(TransactionType.XA)  // 支持TransactionType.LOCAL, TransactionType.XA, TransactionType.BASE
public void insert() {
    jdbcTemplate.execute("INSERT INTO t_order (user_id, status) VALUES (?, ?)", (PreparedStatementCallback<Object>) preparedStatement -> {
        preparedStatement.setObject(1, i);
        preparedStatement.setObject(2, "init");
        preparedStatement.executeUpdate();
    });
}

分布式事務管理器的特有配置

XA事務管理器參數(shù)配置(可選)

ShardingSphere默認的XA事務管理器為Atomikos劈彪,在項目的logs目錄中會生成xa_tx.log, 這是XA崩潰恢復時所需的日志竣蹦,請勿刪除。

也可以通過在項目的classpath中添加jta.properties來定制化Atomikos配置項沧奴。具體的配置規(guī)則請參考Atomikos的官方文檔痘括。

BASE柔性事務管理器(SEATA-AT配置)

  • 1、按照seata-work-shop中的步驟滔吠,下載并啟動seata server纲菌,參考 Step6 和 Step7即可。

  • 2疮绷、在每一個分片數(shù)據(jù)庫實例中執(zhí)創(chuàng)建undo_log表(以MySQL為例)

CREATE TABLE IF NOT EXISTS `undo_log`
(
  `id`            BIGINT(20)   NOT NULL AUTO_INCREMENT COMMENT 'increment id',
  `branch_id`     BIGINT(20)   NOT NULL COMMENT 'branch transaction id',
  `xid`           VARCHAR(100) NOT NULL COMMENT 'global transaction id',
  `context`       VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',
  `rollback_info` LONGBLOB     NOT NULL COMMENT 'rollback info',
  `log_status`    INT(11)      NOT NULL COMMENT '0:normal status,1:defense status',
  `log_created`   DATETIME     NOT NULL COMMENT 'create datetime',
  `log_modified`  DATETIME     NOT NULL COMMENT 'modify datetime',
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8 COMMENT ='AT transaction mode undo table';
  • 3翰舌、在classpath中增加seata.conf
client {
    application.id = example    ## 應用唯一id
    transaction.service.group = my_test_tx_group   ## 所屬事務組
}
  • 4、根據(jù)實際場景修改seata的file.conf和registry.conf文件

注意:

shardingjdbc對數(shù)據(jù)庫的訪問有一些限制:
官方站的說明:https://shardingsphere.apache.org/document/legacy/4.x/document/cn/manual/sharding-jdbc/unsupported-items/

四冬骚、 ShardingSphere集成Nacos配置中心

4.1 集成配置中心

為了集成配置中心椅贱,第一步需要引入 ShardingSphere 中與編排治理相關的依賴包懂算。在 Spring Boot 環(huán)境中,這個依賴包是 sharding-jdbc-orchestration-spring-boot-starter:

<dependency>
    <groupId>org.apache.shardingsphere</groupId>         
    <artifactId>sharding-jdbc-orchestration-spring-boot-starter</artifactId>
</dependency>

引入Nacos配置相關依賴

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-orchestration-reg-nacos</artifactId>
</dependency>
 
<dependency>
    <groupId>com.alibaba.nacos</groupId>
    <artifactId>nacos-client</artifactId>
</dependency>

如果是ZooKeeeper作為配置中心的話庇麦,需引入相關依賴

<dependency>
    <groupId>org.apache.shardingsphere</groupId>         
    <artifactId>sharding-orchestration-reg-zookeeper-curator</artifactId>
</dependency>

4.2 掌握配置項

針對配置中心计技,ShardingSphere 提供了一系列的 DataSource,包括用于數(shù)據(jù)分片的 OrchestrationShardingDataSource山橄、用于讀寫分離的 OrchestrationMasterSlaveDataSource 以及用于數(shù)據(jù)脫敏的 OrchestrationEncryptDataSource垮媒。圍繞這些 DataSource,也存在對應的 DataSourceFactory 工廠類航棱。這里以 OrchestrationMasterSlaveDataSourceFactory 為例來看創(chuàng)建 DataSource 所需要的配置類:

public final class OrchestrationMasterSlaveDataSourceFactory {
    
    public static DataSource createDataSource(final Map<String, DataSource> dataSourceMap, final MasterSlaveRuleConfiguration masterSlaveRuleConfig, 
                                              final Properties props, final OrchestrationConfiguration orchestrationConfig) throws SQLException {
        if (null == masterSlaveRuleConfig || null == masterSlaveRuleConfig.getMasterDataSourceName()) {
            return createDataSource(orchestrationConfig);
        }
        MasterSlaveDataSource masterSlaveDataSource = new MasterSlaveDataSource(dataSourceMap, new MasterSlaveRule(masterSlaveRuleConfig), props);
        return new OrchestrationMasterSlaveDataSource(masterSlaveDataSource, orchestrationConfig);
    }
     …
}

可以看到睡雇,這里存在一個治理規(guī)則配置類 OrchestrationConfiguration,而在其他的 DataSourceFactory 中所使用的也是這個配置類:

public final class OrchestrationConfiguration {
    //治理規(guī)則名稱
    private final String name;
    //注冊(配置)中心配置類
    private final RegistryCenterConfiguration regCenterConfig;
    //本地配置是否覆寫服務器配置標志位
    private final boolean overwrite;
}

在 OrchestrationConfiguration 中我們看到了用于指定本地配置是否覆寫服務器配置的 overwrite 標志位饮醇,也看到了一個注冊中心的配置子類 RegistryCenterConfiguration它抱。RegistryCenterConfiguration 包的含內容比較多,我們截取最常見最通用的部分配置項:

public final class RegistryCenterConfiguration extends TypeBasedSPIConfiguration {
  
    //配置中心服務器列表
    private String serverLists;   
    //命名空間
    private String namespace;
       …
}

這里包含了配置中心服務器列表 serverLists 以及用于標識唯一性的命名空間 namespace驳阎。因為 RegistryCenterConfiguration 繼承了 TypeBasedSPIConfiguration抗愁,所以也就自動帶有 type 和 properties 這兩個配置項。

4.3 在Nacos創(chuàng)建配置

spring.shardingsphere.datasource.names=dsmaster,dsslave0,dsslave1
 
spring.shardingsphere.datasource.dsmaster.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.dsmaster.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.dsmaster.jdbc-url=jdbc:mysql://localhost:3306/dsmaster
spring.shardingsphere.datasource.dsmaster.username=root
spring.shardingsphere.datasource.dsmaster.password=root
 
spring.shardingsphere.datasource.dsslave0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.dsslave0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.dsslave0.jdbc-url=jdbc:mysql://localhost:3306/dsslave0
spring.shardingsphere.datasource.dsslave0.username=root
spring.shardingsphere.datasource.dsslave0.password=root
 
spring.shardingsphere.datasource.dsslave1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.dsslave1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.dsslave1.jdbc-url=jdbc:mysql://localhost:3306/dsslave1
spring.shardingsphere.datasource.dsslave1.username=root
spring.shardingsphere.datasource.dsslave1.password=root
 
spring.shardingsphere.masterslave.load-balance-algorithm-type=random
spring.shardingsphere.masterslave.name=health_ms
spring.shardingsphere.masterslave.master-data-source-name=dsmaster
spring.shardingsphere.masterslave.slave-data-source-names=dsslave0,dsslave1
 
spring.shardingsphere.props.sql.show=true

4.4 ShardingSphere配置開關

  • spring.shardingsphere.orchestration.overwrite=true:采用本地配置呵晚。
  • spring.shardingsphere.orchestration.overwrite=false:只從配置中心讀取配置蜘腌。

選擇使用阿里巴巴的 Nacos來構建配置中心服務器

spring.shardingsphere.orchestration.name=health_ms
spring.shardingsphere.orchestration.overwrite=false
spring.shardingsphere.orchestration.registry.type=nacos
spring.shardingsphere.orchestration.registry.server-lists=localhost:8848
spring.shardingsphere.orchestration.registry.namespace=

如果采用其他配置配置中心需修改spring.shardingsphere.orchestration.registry.type并提供對應的 server-lists即可。

參考:
https://shardingsphere.apache.org/document/legacy/4.x/document/cn/features/transaction/

https://segmentfault.com/a/1190000023379017

https://blog.csdn.net/qq_35731570/article/details/121394495

http://t.zoukankan.com/architectforest-p-13639608.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末饵隙,一起剝皮案震驚了整個濱河市撮珠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌金矛,老刑警劉巖芯急,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異驶俊,居然都是意外死亡娶耍,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門饼酿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來榕酒,“玉大人,你說我怎么就攤上這事故俐∠胗ィ” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵药版,是天一觀的道長辑舷。 經(jīng)常有香客問我,道長槽片,這世上最難降的妖魔是什么何缓? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任肢础,我火速辦了婚禮,結果婚禮上歌殃,老公的妹妹穿的比我還像新娘乔妈。我一直安慰自己,他們只是感情好氓皱,可當我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著勃刨,像睡著了一般波材。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上身隐,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天廷区,我揣著相機與錄音,去河邊找鬼贾铝。 笑死隙轻,一個胖子當著我的面吹牛,可吹牛的內容都是我干的垢揩。 我是一名探鬼主播玖绿,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼叁巨!你這毒婦竟也來了斑匪?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤锋勺,失蹤者是張志新(化名)和其女友劉穎蚀瘸,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體庶橱,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡贮勃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了苏章。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寂嘉。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖布近,靈堂內的尸體忽然破棺而出垫释,到底是詐尸還是另有隱情,我是刑警寧澤撑瞧,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布棵譬,位于F島的核電站,受9級特大地震影響预伺,放射性物質發(fā)生泄漏订咸。R本人自食惡果不足惜曼尊,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望脏嚷。 院中可真熱鬧骆撇,春花似錦、人聲如沸父叙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春布疼,著一層夾襖步出監(jiān)牢的瞬間城豁,已是汗流浹背吴旋。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工矾策, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人悠咱。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓蒸辆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親析既。 傳聞我的和親對象是個殘疾皇子躬贡,可洞房花燭夜當晚...
    茶點故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內容