案例源碼使用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/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/
版權所有,歡迎轉載,轉載請注明原文作者及出處。