1. 程式人生 > 實用技巧 >分散式事務:SpringBoot+Dubbo+Seata+Nacos 實現案例

分散式事務:SpringBoot+Dubbo+Seata+Nacos 實現案例

案例原始碼使用SpringBoot 2.3.2 + Dubbo 2.7.6 + Mybatis 1.3.2 + Nacos 1.3.2 + Seata 1.3.0整合來實現Dubbo分散式事務管理,使用Nacos 作為 Dubbo和Seata的註冊中心和配置中心,使用 MySQL 資料庫和 MyBatis來操作資料庫。

案例說明

專案包含四個模組,consumer模組依賴其他三個模組。

示例採用TCC模式與AT模式混合使用模式,所以相容純資料庫事務和其他事務的支援。

建立資料庫

要求:示例使用MySQL資料庫,需要具有InnoDB引擎的MySQL。

注意:實際上,在示例用例中,這3個服務應該有3個數據庫。 但是,為了簡單起見,我們只建立一個數據庫並配置3個數據源,建立一個數據庫seata。

建立回滾日誌表

SEATA 的AT 模式需要UNDO_LOG表,用於支援回滾操作。

-- 注意此處0.3.0+ 增加唯一索引 ux_undo_log

CREATE TABLE `undo_log` (

  `id` bigint(20) NOT NULL AUTO_INCREMENT,

  `branch_id` bigint(20) NOT NULL,

  `xid` varchar(100) NOT NULL,

  `context` varchar(128) NOT NULL,

  `rollback_info` longblob NOT NULL,

  `log_status` int
(11) NOT NULL, `log_created` datetime NOT NULL, `log_modified` datetime NOT NULL, `ext` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

建立業務相關表

在action-db-provider專案的sql目錄下也可以找到SQL指令碼。

CREATE
TABLE `t_user` ( `id`bigint(32) NOT NULL AUTO_INCREMENT, `userName`varchar(32) NOT NULL, `passWord`varchar(50) NOT NULL, `realName`varchar(32) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

Nacos伺服器

示例使用Nacos註冊中心,需要先安裝Nacos伺服器。

下載軟體

下載地址:https://github.com/alibaba/nacos/releases

從下載地址下載伺服器軟體包,示例要求使用1.3.2版本,解壓縮後啟動。

執行模式

單機模式

因為下載下來的Nacos的啟動指令碼預設是使用叢集模式啟動的,需要依賴MySQL資料庫,如果想使用單機模式,修改bin目錄下的startup.cmd,設定其啟動模式為單機模式。

叢集模式

1. 將nacos/conf/nacos-mysql.sql匯入自己的資料庫

2. 配置修改nacos/conf/application.properties

spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=123456

啟動服務

啟動指令碼在bin目錄下,進入目錄,執行指令碼啟動服務。

Windows:cmd> startup.cmd

Linux/Mac:bash> startup.sh -m standalone

關閉服務:

Windows:cmd> shutdown.cmd

Linux/Mac:bash> shutdown.sh

訪問地址

nacos服務預設埠是8848 瀏覽器輸入:http://127.0.0.1:8848/nacos

登陸賬號和密碼都是 nacos,登陸成功的畫面如下:

參考資料

官方網站:https://nacos.io/zh-cn/

官方文件:https://nacos.io/zh-cn/docs/quick-start.html

Seata伺服器

下載軟體

下載地址: https://github.com/seata/seata/releases

從下載地址下載伺服器軟體包,這裡下載1.3.0版本。

可以直接下載二進位制軟體包,也可以下載原始碼編譯。

原始碼編譯命令如下:

mvn -Prelease-all -DskipTests clean install –U

Seata配置

在seata的目錄下需要關注兩個配置檔案。

首先是registry.conf,選擇seata使用的註冊中心,可選項包含file 、nacos 、eureka、redis、zk、consul、etcd3、sofa,預設配置是nacos。如果你的nacos地址賬號等資訊與預設配置不一致,將配置改成你自己的。

另外file.conf配置了seata的儲存模式,seata的儲存模式包括:file、db、redis,db、redis模式需要將連線資訊配置成你自己的。

匯入配置

如果下載的是二進位制安裝包,以下檔案需要到git倉庫原始碼或下載原始碼包獲取。使用db模式匯入配置,進入原始碼目錄,mysql.sql為seata庫必須的表,執行sql即可。

複製config.txt檔案到seata根目錄。

複製nacos中的nacos-config.sh、nacos-config.py到seata的conf目錄。

然後命令列執行 sh nacos-config.sh hostip 匯入配置到Nacos即可,匯入完成之後,可以登入Nacos檢視配置。

啟動服務

啟動指令碼在bin目錄下,進入目錄,執行指令碼啟動服務。

Windows:cmd> seata-server.bat

Linux/Mac:bash> seata-server.sh

啟動時可以指定包括主機、埠、日誌儲存模式等啟動引數。

引數說明:

--host, -h

The host to bind,Default: 0.0.0.0

--port, -p

The port to listen,Default: 8091

--storeMode, -m

log store mode : file、db Default: file

--help

比如:

sh seata-server.sh -p 8091 -h 127.0.0.1 -m file

參考資料

官方網站:https://seata.io/zh-cn/index.html

官方文件:https://seata.io/zh-cn/docs/overview/what-is-seata.html

搭建原始碼專案

專案結構

專案結構如下,專案包含四個模組,consumer模組依賴其他三個模組。

springboot-dubbo-seata-tccat

專案父模組,包含四個子模組,並提供了nacos、seata、dubbo的依賴。

service-consumer

提供分散式事務的服務和測試介面,通過RPC呼叫其他幾個子模組的服務。

在TccController裡提供了測試提交和回滾的相關介面,程式碼如下:

/**
 * 發起事務控制器
 *
 * @author louis
 */
@RestController
public class TccController {

    @Resource
    private TccTransactionService tccTransactionService;

    /**
     * 分散式事務提交示例介面
     */
    @GetMapping("/testCommit")
    public String testCommit() {
        String result = tccTransactionService.testCommit();
        return "----------test transaction commit---------- \n" + result;
    }

    /**
     * 分散式事務回滾示例介面
     */
    @GetMapping("/testRollback")
    public String testRollback() {
        String result = "";
        try {
            tccTransactionService.testRollback();
        } catch (Throwable t) {
            result = t.getMessage();
        }
        return  "----------test transaction rollback ---------- \n" + result;
    }
}

具體的的分散式服務在TccTransactionService中實現,方法內容如下:

@Service
public class TccTransactionService {

    @Resource
    private TccActionOne tccActionOne;
    @Resource
    private TccActionTwo tccActionTwo;
    @Reference(version = "1.0.0", group = "tcc")
    private UserService userService;

    /**
     * 測試分散式事務提交示例
     */
    @GlobalTransactional
    public String testCommit() {
        // 第一個TCC 事務參與者
        String result = tccActionOne.prepare("action-one-commit").getMessage();
        // 第二個TCC 事務參與者
        result = result + "\n" + tccActionTwo.prepare("action-two-commit").getMessage();
        // 資料庫操作
        userService.save(getUser());
        return result;
    }

    /**
     * 測試分散式事務回滾示例
     */
    @GlobalTransactional
    public String testRollback() {
        //第一個TCC 事務參與者
        String result = tccActionOne.prepare("action-one-rollback").getMessage();
        // 第二個TCC 事務參與者
        result = result + "\n" + tccActionTwo.prepare("action-two-rollback").getMessage();
        // 資料庫操作
        userService.save(getUser());
        throw new RuntimeException(result);
    }
}

相關配置檢視application.yml配置檔案。

seata:
application-id: ${spring.application.name}
tx-service-group: my_test_tx_group # 事務分組,與seata-server配置保持一致
registry:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
namespace:
cluster: default
config:
type: nacos
nacos:
namespace:
server-addr: 127.0.0.1:8848

action-one-provider

提供TCC參與者,編寫prepare、commit、rollback三個方法。

@Component
@Service(version = "1.0.0", group = "tcc")
public class ActionOneServiceImpl implements ActionOneService {

    @Override
    public String prepare(String param) {
        String result = ":::: action-one-provider prepare, rpc called success, param:" + param + ".";
        System.out.println(result);
        return result;
    }

    @Override
    public String commit(String param) {
        String result = ":::: action-one-provider commit, rpc called success, param:" + param + ".";
        System.out.println(result);
        return result;
    }

    @Override
    public String rollback(String param) {
        String result = ":::: action-one-provider rollback, rpc called success, param:" + param + ".";
        System.out.println(result);
        return result;
    }
}

action-two-provider

同actiono-one-provider一樣,提供TCC參與者,編寫prepare、commit、rollback三個方法。

action-db-provider

提供資料庫操作服務,用於測試AT模式。

POM檔案添加了Mybatis和MySQL的支援。

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.2</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

UserServiceImpl提供了使用者表相關的CRUD服務。

@Component
@Service(version = "1.0.0", group = "tcc")
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Override
    public User save(User user) {
        if(user.getId() == null || "".equals(user.getId())) {
            userMapper.insert(user);
        } else {
            userMapper.updateByPrimaryKeySelective(user);
        }
        return user;
    }

...

}

執行示例程式

啟動服務

直接執行各個模組的Application啟動應用即可。

測試服務

成功案例

測試一下介面,觀察控制檯輸出和資料庫記錄。

測試介面:

http://localhost:8005/testCommit

回滾案例

測試一下介面,觀察控制檯輸出和資料庫記錄。

測試介面:

http://localhost:8005/testRollback

原始碼下載

碼雲:https://gitee.com/liuge1988/seata-demo.git


作者:朝雨憶輕塵
出處:https://www.cnblogs.com/xifengxiaoma/
版權所有,歡迎轉載,轉載請註明原文作者及出處。