LCN分佈式事務框架整合
場景圖:我們是要在訂單服務中,調用庫存服務。當下一個訂單的時候,就對庫存-1操作
1、首先要把tx-manager(分佈式協調者)項目搭建起來
我這裏使用的是最新的lcn版本依賴
<dependency>
<groupId>com.codingapi.txlcn</groupId>
<artifactId>txlcn-tm</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
pom.xml文件
spring.application.name=tx-manager
server.port=8899
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=123456
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.use-generated-keys=true
#tx-lcn.logger.enabled=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=100000
#參數延遲刪除時間單位ms
#tx-lcn.message.netty.attr-delay-time=10000
#tx-lcn.manager.concurrent-level=128
# 開啓日誌
tx-lcn.logger.enabled=true
logging.level.com.codingapi=debug
#redis 主機
spring.redis.host=127.0.0.1
#redis 端口
spring.redis.port=6379
#redis 密碼
spring.redis.password=123456
# eureka地址
eureka.client.service-url.defaultZone=http://127.0.0.1:8100/eureka/
eureka.instance.prefer-ip-address=true
# TM後臺登陸密碼,默認值爲codingapi
tx-lcn.manager.admin-key=admin
tx-manager項目啓動類
@SpringBootApplication
@EnableTransactionManagerServer
@EnableEurekaClient
public class TransactionManagerApplication {
public static void main(String[] args) {
SpringApplication.run(TransactionManagerApplication.class, args);
}
}
3、融入服務中,這裏我使用 order服務和stock服務
在要使用LCN分佈式框架的服務中導入依賴
<!-- 引入分佈式事務解決框架LCN start-->
<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>
<!-- 引入分佈式事務解決框架LCN end-->
Order啓動類:
/**
* 訂單服務
*
* @author liyue
* @date 2019/12/9 12:11
*/
@EnableEurekaClient
@SpringBootApplication
@EnableFeignClients
@MapperScan(basePackages = "com.leeue.mapper")
/**TC開啓分佈式事務註解**/
@EnableDistributedTransaction
public class OrderApp {
public static void main(String[] args) {
SpringApplication.run(OrderApp.class, args);
}
}
order方法實現類
@LcnTransaction //分佈式事務註解
@Transactional(rollbackFor = Exception.class)//事務註解
@Override
public ResponseBase addOrderAndStock(int i) throws Exception {
OrderEntity orderEntity = new OrderEntity();
orderEntity.setName("永久會員充值");
orderEntity.setOrderCreatetime(new Date());
// 價格是300元
orderEntity.setOrderMoney(300d);
// 狀態爲 未支付
orderEntity.setOrderState(0);
Long commodityId = 30L;
// 商品id
orderEntity.setCommodityId(commodityId);
// 1.先下單,創建訂單
int orderResult = orderMapper.addOrder(orderEntity);
System.out.println("orderResult:" + orderResult);
// 2.下單成功後,調用庫存服務
ResponseBase inventoryReduction = stockFeign.inventoryReduction(commodityId);
if (inventoryReduction.getRtnCode() != 200) {
// 第一種方法,使用手動事務 -
// TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
// 第二種方法,使用aop,捕獲異常後,進行手動事務回滾,獲取將異常拋出給上一層,外面回滾。
throw new Exception("調用庫存服務接口失敗,開始回退訂單事務代碼");
}
int reuslt = 1 / i;
return setResultSuccess("下單成功!");
}
同理:
Stock啓動類
/**
* 庫存服務
*
* @author liyue
* @date 2019/12/9 12:13
*/
@EnableEurekaClient
@SpringBootApplication
@EnableFeignClients
@MapperScan(basePackages = "com.leeue.mapper")
/**TC開啓分佈式事務註解**/
@EnableDistributedTransaction
public class StockApp {
public static void main(String[] args) {
SpringApplication.run(StockApp.class, args);
}
}
stock實現方法:
@LcnTransaction //分佈式事務註解
@Transactional
@RequestMapping("/inventoryReduction")
public ResponseBase inventoryReduction(@RequestParam("commodityId") Long commodityId) {
if (commodityId == null) {
return setResultError("商品id不能爲空!");
}
// 1.查詢該商品id 是否存在
StockEntity stockEntity = stockMapper.selectStock(commodityId);
if (stockEntity == null) {
return setResultError("商品id不存在!");
}
// 2.判斷商品是否有超賣
if (stockEntity.getStock() <= 0) {
return setResultError("當前商品已經買完啦!");
}
// 3.減去庫存1
int updateStockResult = stockMapper.updateStock(commodityId);
if (updateStockResult <= 0) {
return setResultError("修改庫存失敗!");
}
return setResultSuccess("修改庫存成功!");
}
搭建中遇到了問題:
Connect socket(/127.0.0.1:8070) fail. 6000ms latter try again.
這個問題其實是我tx-manager項目中配置文件這個沒有打開 這個地方一定要開放出來
# TxClient連接請求端口 這個地方一定要進行開放
tx-lcn.manager.port=8070
如果其他情況可以查看官網git
https://github.com/codingapi/tx-lcn/issues/261
Tx-manager後臺管理地址:http://127.0.0.1:8899/admin/index.html#/TxClient
如果tx-manager突然掛了:
- 1、後臺會報異常,non tx-manager is alive
- 2、如果在提交的時候tx-manager突然掛了,事務還是會進行回滾,因爲開始的都是假提交,沒有真正的提交的都會出現事務的回滾。
搭建源碼: