SpringCloud中的分佈式事務

一、基於XA的兩階段提交方案

兩階段提交方案應用非常廣泛,幾乎所有商業OLTP數據庫都支持XA協議。但是兩階段提交方案鎖定資源時間長,對性能影響很大,基本不適合解決微服務事務問題。
在這裏插入圖片描述

二、TCC解決方案

TCC方案在電商、金融領域落地較多。TCC方案其實是兩階段提交的一種改進。其將整個業務邏輯的每個分支顯式的分成了Try、Confirm、Cancel三個操作。Try部分完成業務的準備工作,confirm部分完成業務的提交,cancel部分完成事務的回滾。基本原理如下圖所示。
事務開始時,業務應用會向事務協調器註冊啓動事務。之後業務應用會調用所有服務的try接口,完成一階段準備。之後事務協調器會根據try接口返回情況,決定調用confirm接口或者cancel接口。如果接口調用失敗,會進行重試。
微服務倡導服務的輕量化、易部署,而TCC方案中很多事務的處理邏輯需要應用自己編碼實現,複雜且開發量大。

在這裏插入圖片描述

三、分佈式事務中間件解決方案

分佈式事務中間件其本身並不創建事務,而是基於對本地事務的協調從而達到事務一致性的效果。典型代表有:阿里的GTS(https://www.aliyun.com/aliware/txc)、開源應用LCN。
其實現原理如下
在這裏插入圖片描述

  1. LCN分佈式事務框架

a. 在設計框架之初的1.0 ~ 2.0的版本時,框架設計的步驟是如下的,各取其首字母得來的LCN命名。鎖定事務單元(lock)、確認事務模塊狀態(confirm)、通知事務(notify)
b. 創建事務組:是指在事務發起方開始執行業務代碼之前先調用TxManager創建事務組對象,然後拿到事務標示GroupId的過程。
c. 添加事務組:添加事務組是指參與方在執行完業務方法以後,將該模塊的事務信息添加通知給TxManager的操作。
d. 關閉事務組:是指在發起方執行完業務代碼以後,將發起方執行結果狀態通知給TxManager的動作。當執行完關閉事務組的方法以後,TxManager將根據事務組信息來通知相應的參與模塊提交或回滾事務

tx-lcn官方地址:https://www.txlcn.org/
tx-lcn Github地址:https://github.com/codingapi/tx-lcn
tx-lcn服務下載地址:https://pan.baidu.com/s/1cLKAeE#list/path=%2F
tx-lcn服務源碼地址:https://github.com/codingapi/tx-lcn/tree/master/tx-manager

  1. LCN應用 - 搭建tx-manager服務

LCN是通過一個獨立的微服務tx-manager作爲分佈式事務控制服務端(事務協調器)。需要執行分佈式事務控制的微服務應用都通過遠程服務調用的方式,在tx-manager上標記事務組,在執行事務處理後,將本地事務狀態發送到tx-manager中對應的事務組上,tx-manager會根據具體的狀態來通知相應的微服務應用提交或回滾。
tx-manager也是使用Spring Cloud開發的一個微服務應用,在搭建過程上是非常簡單的。
下載tx-manager事務協調器zip壓縮包:https://pan.baidu.com/s/1cLKAeE#list/path=%2F
壓縮包解壓後內容如下
在這裏插入圖片描述

修改application.properties配置文件,提供本地微服務應用的Eureka註冊中心配置、redis配置。其中redis是事務協調器在處理事務組時使用的臨時存儲

##########################txmanager-start#######################
#服務端口
server.port=8899

#tx-manager不得修改
spring.application.name=tx-manager

spring.mvc.static-path-pattern=/**
spring.resources.static-locations=classpath:/static/
###########################txmanager-end#######################

#eureka 地址
eureka.client.service-url.defaultZone=http://127.0.0.1:8761/eureka/
eureka.instance.prefer-ip-address=true

#############################redis-start#########################
##redis 單點環境配置
#redis
spring.redis.database=0
spring.redis.timeout=0
spring.redis.host=192.168.1.136
spring.redis.port=6379
spring.redis.pool.max-active=100
spring.redis.pool.max-wait=3000
spring.redis.pool.max-idle=200
spring.redis.pool.min-idle=50
spring.redis.pool.timeout=600
##############################redis-end##########################

###############################LCN-start########################
tm.transaction.netty.delaytime = 5
tm.transaction.netty.hearttime = 15
tm.redis.savemaxtime=30
tm.socket.port=9999
tm.socket.maxconnection=100
tm.compensate.auto=false
tm.compensate.notifyUrl=http://ip:port/path
tm.compensate.tryTime=30
tm.compensate.maxWaitTime=5000

logging.level.com.codingapi=debug

將修改後的application.properties配置文件打包到tx-manager-x.x.x.jar中,替代jar中原有的默認配置文件。
使用命令: java -jar tx-manager-x.x.x.jar啓動微服務。
測試tx-manager事務協調器是否啓動成功可以訪問http://ip:8899/。如下結果代表事務協調器啓動成功
在這裏插入圖片描述

在微服務中使用LCN實現分佈式事務管理
在所有需要處理分佈式事務的微服務中增加下述依賴:爲統一資源版本,使用properties統一管理版本信息

	<properties>
		<lcn.last.version>4.1.0</lcn.last.version>
	</properties>
		<dependency>
			<groupId>com.codingapi</groupId>
			<artifactId>transaction-springcloud</artifactId>
			<version>${lcn.last.version}</version>
			<exclusions>
				<exclusion>
					<groupId>org.slf4j</groupId>
					<artifactId>*</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>com.codingapi</groupId>
			<artifactId>tx-plugins-db</artifactId>
			<version>${lcn.last.version}</version>
			<exclusions>
				<exclusion>
					<groupId>org.slf4j</groupId>
					<artifactId>*</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

在全局配置文件中增加下述配置

# 定義事務協調器所在位置。根據具體環境定義其中的IP地址和端口。
tm.manager.url=http://127.0.0.1:8899/tx/manager/

使用LCN做分佈式事務管理時,微服務應用內必須提供一個用於獲取txUrl(txUrl就是全局配置文件中定義的tm.manager.url)的類型實現,這個類可以使用獨立應用定義,在微服務應用中引入。本案例中爲了方便,直接在所有的微服務應用中提供對應代碼實現。具體如下

@Service
public class TxManagerTxUrlServiceImpl implements TxManagerTxUrlService {
	@Value("${tm.manager.url}")
	private String url;

	@Override
	public String getTxUrl() {
		return url;
	}
}

在分佈式事務管理代碼中增加註解@TxTransaction。在業務調用方增加的註解需要屬性isStart=true。而被調用方則不需要定義任何的註解屬性。如:
交易服務調用了訂單服務,那麼交易服務中代碼

@TxTransaction(isStart=true)
@Transactional
public void trade() {
    //本地調用
    tradeDao.save();
    //遠程調用方
    orderService.order();
}

訂單服務中代碼

@Transactional
@TxTransaction
public void order() {
    //本地調用
    orderDao.save();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章