TX-LCN分散式事務使用方案

快些兒發表於2020-11-13

網上貌似有很多微服務的框架,找了半天,貌似只有TX-LCN有完整的搭建,所以先摘抄一些,應對面試

介紹

TX-LCN分散式事務框架,LCN並不生產事務,LCN只是本地事務的協調工,LCN是一個高效能的分散式事務框架,相容dubbo、springcloud框架,支援RPC框架擴充,支援各種ORM框架、NoSQL、負載均衡、事務補償

特性

  1. 一致性,通過TxManager協調控制與事務補償機制確保資料一致性

  2. 易用性,僅需要在業務方法上新增@TxTransaction註解即可

@TxTransaction註解是分散式事務的標示。

若存在業務方法:a->b b->c b->d,那麼開啟分散式事務註解的話,只需要在a方法上新增@TxTransaction即可。

  1. 高可用,專案模組不僅可高可用部署,事務協調器也可叢集化部署
  2. 擴充套件性,支援各種RPC框架擴充套件,支援通訊協議與事務模式擴充套件

官方文件

https://www.txlcn.org/zh-cn/docs/preface.html

流程圖實現

在這裡插入圖片描述

  1. 服務發起者 在事務協調者內建立事務組,並將本事務加入事務組
  2. 事務參與者加入事務組,直到有結束標記出現
  3. 事務協調者向所有的事務參與者傳送詢問,是否能夠提交!
  4. 全部提交則事務組提交!有一個回滾標記則事務組回滾!
  5. 事務組執行操作之後,釋放所有鎖資源!

搭建分散式服務

下載官網提供的最新版的TM專案,修改配置檔案(PS:由於官網的下載地址打不開,我們去GitHub上面下載例子:https://github.com/codingapi/txlcn-demo),參考txlcn-demo-tm工程,在我們之前的專案下面建立一個springboot專案叫txlcn-tm

參照官網修改配置檔案,詳細的TM配置請戳:https://www.txlcn.org/zh-cn/docs/setting/manager.html,開發階段最好開啟日誌,並設定為debug等級,這樣方便追蹤排查問題

spring.application.name=txlcn-tm
server.port=7970

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto=validate

# TM後臺登陸密碼
tx-lcn.manager.admin-key=123456

tx-lcn.manager.host=127.0.0.1
tx-lcn.manager.port=8070

# 開啟日誌,預設為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}logging.level.com.codingapi.txlcn=DEBUG

#redis 主機
spring.redis.host=127.0.0.1
#redis 埠
spring.redis.port=6379
#redis 密碼
spring.redis.password=

在啟動類新增註解 @EnableTransactionManagerServer

package cn.huanzi.qch.txlcn.tm;

import com.codingapi.txlcn.tm.config.EnableTransactionManagerServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableTransactionManagerServer
public class TxlcnTmApplication {

    public static void main(String[] args) {
        SpringApplication.run(TxlcnTmApplication.class, args);
    }

}

我們的Redis服務執行起來,然後啟動txlcn-tm,啟動成功後訪問tm後臺管理系統,使用預設密碼登入(可以配置登入密碼),訪問 http://127.0.0.1:7970/admin/index.html進入管理後臺,預設密碼是codingapi,我們這裡配置了123456

啟動TM之前記得先啟動我們的Redis服務,到這裡,我們的tm搭建成功,更多TM介紹,請看官網TM管理手冊:https://www.txlcn.org/zh-cn/docs/manageradmin.html

測試

兩個微服務,Server1和Server2

Server1啟動類

啟動類 注意:啟動類必須新增@EnableDistributedTransaction註解 啟動分散式事務

package com.order;

import com.codingapi.txlcn.tc.config.EnableDistributedTransaction;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * @author huangfu
 */
@EnableEurekaClient
@SpringBootApplication
@EnableFeignClients
@MapperScan("com.order.mapper")
@EnableDistributedTransaction
public class ServerOneApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServerOneApplicatin.class);
    }
}

注意:涉及到分散式事務的一定要新增 @LcnTransaction 註解

Server1Controller

package com.order.server.impl;

import com.codingapi.txlcn.tc.annotation.LcnTransaction;
import com.order.client.ServerTwoClient;
import com.order.mapper.ServerOneMapper;
import com.order.server.ServerOneService;
import com.pojo.ServerOne;
import com.pojo.ServerTwo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author huangfu
 */
@Service
@SuppressWarnings("all")
public class ServerOneServiceImpl implements ServerOneService {
    @Autowired
    private ServerOneMapper serverOneMapper;
    @Autowired
    private ServerTwoClient serverTwoClient;

    @Override
    @LcnTransaction
    @Transactional(rollbackFor = Exception.class)
    public void insertData(ServerOne serverOne,String id) {
        serverOneMapper.insertData(serverOne);
        ServerTwo serverTwo = new ServerTwo(serverOne.getId(),serverOne.getName());
        serverTwoClient.addData2(serverTwo);
        if("1".equals(id)){
            throw new RuntimeException("自定義異常");
        }
        System.out.println("---------------服務一執行完成---------------");
    }
}

Server1利用Feign遠端呼叫Server2

package com.order.client;

import com.codingapi.txlcn.tc.annotation.LcnTransaction;
import com.pojo.ServerTwo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * @author huangfu
 */
@FeignClient(value = "server2")
public interface ServerTwoClient {

    @RequestMapping(value = "/addData2",method = RequestMethod.POST)
    public void addData2(@RequestBody ServerTwo serverTwo);
}

本文所有知識引用自:
https://www.oschina.net/p/tx-lcn?hmsr=aladdin1e1
https://www.cnblogs.com/huanzi-qch/p/11057974.html
https://blog.csdn.net/qq_37561309/article/details/101512691

相關文章