SpringCloud 分佈式事務解決方案

TX-LCN分佈式事務框架

隨着互聯化的蔓延,各類項目都逐漸向分佈式服務作轉換。現在微服務已經廣泛存在,本地事務已經沒法知足分佈式的要求,由此分佈式事務問題誕生。 分佈式事務被稱爲世界性的難題,目前分佈式事務存在兩大理論依據:CAP定律 BASE理論。html

官網地址:https://www.txlcn.org/zh-cn/java

GitHun:https://github.com/yizhishang/tx-lcn/mysql

在一個分佈式系統下存在多個模塊協調來完成一次業務。那麼就存在一次業務事務下可能橫跨多種數據源節點的可能。TX-LCN將能夠解決這樣的問題。git

​ 例如存在服務模塊A 、B、 C。A模塊是mysql做爲數據源的服務,B模塊是基於redis做爲數據源的服務,C模塊是基於mongo做爲數據源的服務。若須要解決他們的事務一致性就須要針對不一樣的節點採用不一樣的方案,而且統一協調完成分佈式事務的處理。github

img

方案:redis

​ 若採用TX-LCN分佈式事務框架,則能夠將A模塊採用LCN模式、B/C採用TCC模式就能完美解決。spring

TX-LCN 主要有兩個模塊,Tx-Client(TC) Tx-Manager(TM). TC做爲微服務下的依賴,TM是獨立的服務。sql

  1. 安裝TM須要依賴的中間件: JRE1.8+, Mysql5.6+, Redis3.2+

若是須要手動編譯源碼, 還須要Git, Maven, JDK1.8+數據庫

  1. 建立MySQL數據庫, 名稱爲: tx-manager
  2. 建立數據表
CREATE TABLE `t_tx_exception`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `group_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `unit_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `mod_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `transaction_state` tinyint(4) NULL DEFAULT NULL,
  `registrar` tinyint(4) NULL DEFAULT NULL,
  `remark` varchar(4096) NULL DEFAULT  NULL,
  `ex_state` tinyint(4) NULL DEFAULT NULL COMMENT '0 未解決 1已解決',
  `create_time` datetime(0) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

TM下載與配置

  1. 歷史版本TM下載找到5.0.2.RELEASE的TM, 下載.
  2. 修改配置信息
spring.application.name=tx-manager
server.port=7970
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/tx-manager?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.use-generated-keys=true
# TxManager Host Ip
tx-lcn.manager.host=127.0.0.1
# TxClient鏈接請求端口
tx-lcn.manager.port=8070
# 心跳檢測時間(ms)
tx-lcn.manager.heart-time=15000
# 分佈式事務執行總時間
tx-lcn.manager.dtx-time=30000
#參數延遲刪除時間單位ms
tx-lcn.message.netty.attr-delay-time=10000
tx-lcn.manager.concurrent-level=128
# TM後臺登錄密碼,默認值爲codingapi
tx-lcn.manager.admin-key=123456
logging.level.com.codingapi=debug
#redis 主機
spring.redis.host=127.0.0.1
#redis 端口
spring.redis.port=6379
#redis 密碼
spring.redis.password=
# 開啓日誌,默認爲false
tx-lcn.logger.enabled=true
tx-lcn.logger.driver-class-name=${spring.datasource.driver-class-name}
tx-lcn.logger.jdbc-url=${spring.datasource.url}
tx-lcn.logger.username=${spring.datasource.username}
tx-lcn.logger.password=${spring.datasource.password}
  • # 給出信息都是默認值
    關於詳細配置說明見TM配置
  • application.properties 加載順序以下:
    0、命令行啓動參數指定
    一、file:./config/(當前jar目錄下的config目錄)
    二、file:./(當前jar目錄)
    三、classpath:/config/(classpath下的config目錄)
    四、classpath:/(classpath根目錄)
    發佈的二進制可執行Jar包含一個默認配置文件(也就是4),可按須要覆蓋默認配置
  • 把txlcn-tm的pom打包方式修改爲
<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
</build>
  • 手動編譯TM,簡單指引
# git clone https://github.com/codingapi/tx-lcn.git & cd txlcn-tm
# mvn clean  package '-Dmaven.test.skip=true'

target文件夾下,即爲Ttxlcn-tm-5.0.2.RELEASE.jar

TC微服務模塊

arch

  • 服務A做爲DTX發起方,遠程調用服務B

工程說明

  1. finchley 父項目主要進行依賴管理
  2. common-config 可存方公共配置級工具
  3. common-eureka 服務註冊中心
  4. gateway-zuul 網關
  5. user-server 服務1
  6. money-server 服務2

忽略其餘工程搭建步驟。

事務操做實例

user-server 提供遠程服務,money-server經過fegin發現服務調用進行事務回滾。

這兩個服務須要加入依賴,以下:

<!-- springcloud 分佈式事物 -->
<dependency>
            <groupId>com.codingapi.txlcn</groupId>
            <artifactId>txlcn-tc</artifactId>
            <version>5.0.2.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>com.google.guava</groupId>
                    <artifactId>guava</artifactId>
                </exclusion>
            </exclusions>
 </dependency>
<dependency>
            <groupId>com.codingapi.txlcn</groupId>
            <artifactId>txlcn-txmsg-netty</artifactId>
            <version>5.0.2.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>com.google.guava</groupId>
                    <artifactId>guava</artifactId>
                </exclusion>
            </exclusions>
</dependency>

依賴最好跟隨TM管理器版本,方式出現奇怪問題。

兩個工程的啓動類使用該@EnableDistributedTransaction標記啓動分佈式事務。

兩個工程properties須要加入事務管理器監控地址,以下:

#該配置根據TM打包時的配置進行
tx-lcn.client.manager-address=127.0.0.1:8070

user-servermoney-server插入數據,server實例:

/**
 * user-server
 * @Auhotr:SimpleWu
 * @TxTransaction 使用該註解啓動分佈式事務
 * @Transactional 同時使用spring事務開啓本地事務
 * 插入一個用戶
 */
@Override
@TxTransaction
@Transactional
public int insertUser(Map<String, Object> map) {
    userServerMapper.insert(map);
    return "insertUser success";
}
//fegin調用user-server服務
 @Autowired
 private UserFegin userFegin;

 //對money表操做mapper
 @Autowired
 private MoneyServerMapper moneyServerMapper;

/**
 * user-server
 * @Auhotr:SimpleWu
 * @TxTransaction 使用該註解啓動分佈式事務
 * @Transactional 同時使用spring事務開啓本地事務
 * 插入一個用戶
 */
@Override
@TxTransaction
@Transactional
public String insert() {
        String userId = UUID.randomUUID().toString();

        Map<String,Object> param = new HashMap<>();
        param.put("ID",userId);
        param.put("USER_ID",userId);
        param.put("MONEY",100);
        param.put("USERPASS","12321321");

        //先調用遠程服務測試事務回滾
        System.out.println( userFegin.hello("張三","12321321",userId));

        int i = 0 / 0;

        moneyServerMapper.insert(param);

        return "success " + param;
 }

啓動順序:

  • 部署Redis
  • 部署TM的Jar包
  • 部署Eureka服務註冊中心
  • 部署user-server服務
  • 部署money-server服務
  • 忽略網關等.....

訪問money-server服務 :http://localhost:13000/hello 調用 insert();

int i = 0 / 0;

該行代碼發生異常,UserFegin爲user-server遠程放服務調用後打印"insertUser success"表明調用成功,若是分佈式事務沒有效果,那麼碰見該異常遠程方不會進行回滾。

在本次測試是回滾成功的,就不貼圖了,親自嘗試才能體會到,那種感受。

而後刪除money-server中刪除int i = 0 / 0;從新啓動。

再次調用http://localhost:13000/hello調用 insert(),成功插入兩條數據。

訪問:http://localhost:7970進入TxManager系統後臺,登陸密碼是咱們設置的123456。裏面能夠看到配置信息,以及異常信息日誌,系統日誌。

該篇案例源代碼與工具見:https://github.com/450255266/open-doubi

相關文章
相關標籤/搜索