目錄php
隨着互聯化的蔓延,各類項目都逐漸向分佈式服務作轉換。現在微服務已經廣泛存在,本地事務已經沒法知足分佈式的要求,由此分佈式事務問題誕生。 分佈式事務被稱爲世界性的難題,目前分佈式事務存在兩大理論依據: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
方案:redis
若採用TX-LCN分佈式事務框架,則能夠將A模塊採用LCN模式、B/C採用TCC模式就能完美解決。spring
TX-LCN 主要有兩個模塊,Tx-Client(TC) Tx-Manager(TM). TC做爲微服務下的依賴,TM是獨立的服務。sql
若是須要手動編譯源碼, 還須要Git, Maven, JDK1.8+數據庫
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;
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}
#
給出信息都是默認值<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
# 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
忽略其餘工程搭建步驟。
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-server
和money-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; }
啓動順序:
訪問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