springboot2.x內建lcn5.0.2分布式事務
- 本地運作tx-manager
- 用戶端內建lcn
- lcn架構了解
-
- lcn實作原理
- tx-lcn三種模式
- 事務控制原理
-
- 核心步驟
LCN文檔檢視
LCNgithub代碼下載下傳
本地運作tx-manager
代碼從github下載下傳後導入IDEA目錄如下:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPB9EMFRlT3lEVNBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL4IDNzMTO0kTMzATOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
1.1、修改application.properties(\txlcn-tm\src\main\resources)配置檔案
spring.application.name=TransactionManager
server.port=7970
###############資料庫##################################
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.130.200:3306/tx-manager?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true
spring.datasource.username=pica_dev
spring.datasource.password=pkv#sqvSGn@O1@tg
# 驗證連接配接是否有效。此參數必須設定為非空字元串,下面三項設定成true才能生
spring.datasource.validationQuery=SELECT 1
# 指明連接配接是否被空閑連接配接回收器(如果有)進行檢驗.如果檢測失敗,則連接配接将被從池中去除.
spring.datasource.testWhileIdle=true
# 指明是否在從池中取出連接配接前進行檢驗,如果檢驗失敗,則從池中去除連接配接并嘗試取出另一個
spring.datasource.testOnBorrow=true
# 指明是否在歸還到池中前進行檢驗
spring.datasource.testOnReturn=false
# 以下可省略
# 初始化大小,最小,最大
spring.datasource.initialSize=5
spring.datasource.minIdle=10
spring.datasource.maxActive=1000
# 配置擷取連接配接等待逾時的時間
spring.datasource.maxWait=60000
#配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接配接,機關是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000
#配置一個連接配接在池中最小生存的時間,機關是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000
#打開PSCache,并且指定每個連接配接上PSCache的大小
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
#配置監控統計攔截的filters,去掉後監控界面sql無法統計,'wall'用于防火牆
spring.datasource.filters=stat,wall,log4j
#通過connectProperties屬性來打開mergeSql功能;慢SQL記錄
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=1000;druid.stat.logSlowSql=true
#合并多個DruidDataSource的監控資料
spring.datasource.useGlobalDataSourceStat=true
#spring.datasource.WebStatFilter.exclusions="*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
#spring.datasource.stat-view-servlet.login-username=admin
#spring.datasource.stat-view-servlet.login-password=admin
####################### 資料庫方言 ############################################
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
# 第一次運作可以設定為: create, 為TM建立持久化資料庫表
spring.jpa.hibernate.ddl-auto=update
####################### Redis ############################################
spring.redis.host=192.168.110.241
spring.redis.port=6380
spring.redis.password=
####################### 事務 ############################################
# TM監聽IP. 預設為 127.0.0.1
tx-lcn.manager.host=127.0.0.1
# TM監聽Socket端口. 預設為 ${server.port} - 100
tx-lcn.manager.port=8070
# 心跳檢測時間(ms). 預設為 300000
tx-lcn.manager.heart-time=300000
# 分布式事務執行總時間(ms). 預設為36000
tx-lcn.manager.dtx-time=8000
# 參數延遲删除時間機關ms 預設為dtx-time值
tx-lcn.message.netty.attr-delay-time=${tx-lcn.manager.dtx-time}
# 事務處理并發等級. 預設為機器邏輯核心數5倍
tx-lcn.manager.concurrent-level=160
# TM背景登陸密碼,預設值為codingapi
tx-lcn.manager.admin-key=123456
# 分布式事務鎖逾時時間 預設為-1,當-1時會用tx-lcn.manager.dtx-time的時間
tx-lcn.manager.dtx-lock-time=${tx-lcn.manager.dtx-time}
# 雪花算法的sequence位長度,預設為12位.
tx-lcn.manager.seq-len=12
# 異常回調開關。開啟時請制定ex-url
tx-lcn.manager.ex-url-enabled=false
# 事務異常通知(任何http協定位址。未指定協定時,為TM提供内置功能接口)。預設是郵件通知
tx-lcn.manager.ex-url=/provider/email-to/[email protected]
# 開啟日志記錄
tx-lcn.logger.enabled=true
1.2、修改/txlcn-tm/pom.xml 檔案 注釋掉docker建構代碼,使用maven建構
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.codingapi.txlcn</groupId>
<artifactId>tx-lcn</artifactId>
<version>5.0.2.RELEASE</version>
</parent>
<artifactId>txlcn-tm</artifactId>
<version>5.0.2.RELEASE</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.codingapi.txlcn</groupId>
<artifactId>txlcn-logger</artifactId>
</dependency>
<dependency>
<groupId>com.codingapi.txlcn</groupId>
<artifactId>txlcn-common</artifactId>
</dependency>
<dependency>
<groupId>com.codingapi.txlcn</groupId>
<artifactId>txlcn-txmsg-netty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
<!-- deploy 注釋掉下 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<mainClass>com.codingapi.txlcn.tm.TMApplication</mainClass>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
<manifestEntries>
<Class-Path>./</Class-Path>
</manifestEntries>
</archive>
<excludes>
<exclude>config/**</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/main/build/package.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<!--docker 建構-->
<!--<plugin>-->
<!--<groupId>com.spotify</groupId>-->
<!--<artifactId>docker-maven-plugin</artifactId>-->
<!--<version>1.0.0</version>-->
<!--<configuration>-->
<!--<imageName>codingapi/txlcn-tm</imageName>-->
<!--<dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>-->
<!--<resources>-->
<!--<resource>-->
<!--<targetPath>/</targetPath>-->
<!--<directory>${project.build.directory}</directory>-->
<!--<include>${project.build.finalName}.jar</include>-->
<!--</resource>-->
<!--</resources>-->
<!--<imageTags>-->
<!--<imageTag>5.0.2</imageTag>-->
<!--</imageTags>-->
<!--<serverId>docker-hub</serverId>-->
<!--<registryUrl>https://index.docker.io/v1/</registryUrl>-->
<!--</configuration>-->
<!--</plugin>-->
</plugins>
</build>
</project>
1.3、tx-manager啟動類如下:
1.3、奔跑起來吧,代碼(/txlcn-tm/src/main/java/com/codingapi/txlcn/tm/TMApplication.java)
通路:http://localhost:7970/admin/index.html
資料配置好的密碼:123456
用戶端內建lcn
2.1、pom.xml引入依賴
<dependency>
<groupId>com.codingapi.txlcn</groupId>
<artifactId>txlcn-tc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.codingapi.txlcn</groupId>
<artifactId>txlcn-txmsg-netty</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
2.2、所有需要使用LCN分布式事務的微服務項目,無論是調用方,還是被調用方的啟動類都需要加上@EnableDistributedTransaction注解,否則分布式事務不生效
2.3、所有需要使用LCN分布式事務的微服務項目,application.yml配置檔案都要引入如下配置,将服務注冊到LCN事務管理者裡面
#lcn分布式事務
tx-lcn:
client:
manager-address: 127.0.0.1:7970
2.4、用戶端調用方法開啟分布式事務
服務A:
服務B:
特别注意:無論是調用方,還是被調用方,都需要設定開啟分布式事務,如果有任何一方不開啟,則分布式事務不生效
lcn架構了解
lcn實作原理
- LCN用戶端(發起方和參與方都必須要注冊到事務協調者中), 建立一個長連接配接。(長連接配接 減寬帶 但是消耗記憶體 連接配接後不斷開)
- 訂單服務(發起方)調用庫存服務接口(參與方)之前,會向TxManager事務協調者建立一個事務的分組id。
-
訂單服務(發起方)調用庫存服務接口(參與方)的時候,會在請求頭(底層是HTTP協定,LCN底層重寫了Feigin用戶端)中存放該事務的分組id,給庫存服務。
(TxClient的代理連接配接池實作了Javax.sql.DataSource接口,并重寫了close方法,事務子產品在送出關閉後,TxClient連接配接池将執行‘假關閉’操作,等待TxManager協調完成事務後再關閉連接配接)
- 如果庫存服務擷取到請求頭中有對應的事務分組id,庫存服務業務邏輯代碼執行完畢的,會采用假關閉,不會送出該事務。
微服務裡面的服務和服務之間 協調在一起 通過注冊中心。
分布式是事務中, 解決事務和事務之間的關系 靠的是類似的平台 TxManager 去協調事務
-
參與方在什麼時候送出事務,不能一直不送出。
肯定在發起方 執行成功下。
訂單服務(發起方)調用庫存服務接口(參與方)之後,如果訂單服務(發起方)執行沒有問題的下,
訂單服務(發起方)使用對應的事務分組id,通知給TxManager事務協調者,讓後TxManager事務協調者在根據該事務分組id,通知給所有的參與方送出事務。
PS:長連接配接 好處減少寬帶傳輸 弊端比較占記憶體。
使用LCN很簡單 加個注解就OK了
需要redis,事務分組ID都是緩存到Redis中的
tx-lcn三種模式
LCN5.0.2有3種模式,分别是LCN模式,TCC模式,TXC模式
- lcn模式:
- 該模式對代碼的嵌入性為低。
- 該模式僅限于本地存在連接配接對象且可通過連接配接對象控制事務的子產品。
- 該模式下的事務送出與復原是由本地事務方控制,對于資料一緻性上有較高的保障。
- 該模式缺陷在于代理的連接配接需要随事務發起方一共釋放連接配接,增加了連接配接占用的時間。
-
TCC模式:
TCC事務機制相對于傳統事務機制(X/Open XA Two-Phase-Commit),其特征在于它不依賴資料總管(RM)對XA的支援,而是通過對(由業務系統提供的)業務邏輯的排程來實作分布式事務。主要由三步操作,Try: 嘗試執行業務、 Confirm:确認執行業務、 Cancel: 取消執行業務。
該模式的特點:
- 該模式對代碼的嵌入性高,要求每個業務需要寫三種步驟的操作。
- 該模式對有無本地事務控制都可以支援使用面廣。
- 資料一緻性控制幾乎完全由開發者控制,對業務開發難度要求高。
-
TXC模式:
TXC模式命名來源于淘寶,實作原理是在執行SQL之前,先查詢SQL的影響資料,然後儲存執行的SQL快走資訊和建立鎖。當需要復原的時候就采用這些記錄資料復原資料庫,目前鎖實作依賴redis分布式鎖控制。
該模式的特點:
- 該模式同樣對代碼的嵌入性低。
- 該模式僅限于對支援SQL方式的子產品支援。
- 該模式由于每次執行SQL之前需要先查詢影響資料,是以相比LCN模式消耗資源與時間要多。
- 該模式不會占用資料庫的連接配接資源。
事務控制原理
TX-LCN由兩大子產品組成, TxClient、TxManager,TxClient作為子產品的依賴架構,提供TX-LCN的标準支援,TxManager作為分布式事務的控制放。事務發起方或者參與反都由TxClient端來控制。
原理圖:
核心步驟
-
建立事務組
是指在事務發起方開始執行業務代碼之前先調用TxManager建立事務組對象,然後拿到事務标示GroupId的過程。
-
加入事務組
添加事務組是指參與方在執行完業務方法以後,将該子產品的事務資訊通知給TxManager的操作。
-
通知事務組
是指在發起方執行完業務代碼以後,将發起方執行結果狀态通知給TxManager,TxManager将根據事務最終狀态和事務組的資訊來通知相應的參與子產品送出或復原事務,并傳回結果給事務發起方。