Apache Seata Mac下的Seata Demo環境搭建

本文來自 Apache Seata官方文檔,歡迎訪問官網,查看更多深度文章。
本文來自 Apache Seata官方文檔,歡迎訪問官網,查看更多深度文章。

Mac下的Seata Demo環境搭建(AT模式)

前言

最近因為工作需要,研究學習了Seata分布式事務框架,本文把自己學習的知識記錄一下

Seata總覽

cloc代碼統計

先看一下seata項目cloc代碼統計(截止到2020-07-20)

在這里插入圖片描述

Java代碼行數大約是 97K

代碼質量

單元測試覆蓋率50%

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

Demo代碼

本文講的Demo代碼是seata-samples項目下的seata-samples-dubbo模塊,地址如下:

https://github.com/apache/incubator-seata-samples/tree/master/dubbo

解決的核心問題

AT模式的Demo例子給出了一個典型的分布式事務場景:

  • 在一個采購交易中,需要:
  1. 扣減商品庫存
  2. 扣減用戶賬號余額
  3. 生成采購訂單
  • 很明顯,以上3個步驟必須:要么全部成功,要么全部失敗,否則系統的數據會錯亂
  • 而現在流行的微服務架構,一般來說,庫存,賬號余額,訂單是3個獨立的系統
  • 每個微服務有自己的數據庫,相互獨立

這里就是分布式事務的場景。

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

解決方案

AT模式解決這個問題的思路其實很簡單,一句話概括就是:

在分布式事務過程中,記錄待修改的數據修改前和修改后的值到undo_log表,萬一交易中出現異常,通過這個里的數據做回滾

當然,具體代碼實現起來,我相信很多細節遠沒這么簡單。

Demo代碼結構

從github上clone最新的代碼

git clone git@github.com:apache/incubator-seata-samples.git

閱讀Demo代碼結構

$ cd seata-samples/dubbo/
$ tree -C  -I 'target' .
.
├── README.md
├── pom.xml
├── seata-samples-dubbo.iml
└── src└── main├── java│   └── io│       └── seata│           └── samples│               └── dubbo│                   ├── ApplicationKeeper.java│                   ├── Order.java│                   ├── service│                   │   ├── AccountService.java│                   │   ├── BusinessService.java│                   │   ├── OrderService.java│                   │   ├── StorageService.java│                   │   └── impl│                   │       ├── AccountServiceImpl.java│                   │       ├── BusinessServiceImpl.java│                   │       ├── OrderServiceImpl.java│                   │       └── StorageServiceImpl.java│                   └── starter│                       ├── DubboAccountServiceStarter.java│                       ├── DubboBusinessTester.java│                       ├── DubboOrderServiceStarter.java│                       └── DubboStorageServiceStarter.java└── resources├── file.conf├── jdbc.properties├── log4j.properties├── registry.conf├── spring│   ├── dubbo-account-service.xml│   ├── dubbo-business.xml│   ├── dubbo-order-service.xml│   └── dubbo-storage-service.xml└── sql├── dubbo_biz.sql└── undo_log.sql13 directories, 27 files
  • 在io.seata.samples.dubbo.starter包下的4個*Starter類,分別模擬上面所述的4個微服務

    • Account
    • Business
    • Order
    • Storage
  • 4個服務都是標準的dubbo服務,配置文件在seata-samples/dubbo/src/main/resources/spring目錄下

  • 運行demo需要把這4個服務都啟動起來,Business最后啟動

  • 主要的邏輯在io.seata.samples.dubbo.service,4個實現類分別對應4個微服務的業務邏輯

  • 數據庫信息的配置文件:src/main/resources/jdbc.properties

時序圖

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

Ok, 趕緊動手, Make It Happen!

運行Demo

MySQL

建表

執行seata-samples/dubbo/src/main/resources/sql的腳本dubbo_biz.sql和undo_log.sql

mysql> show tables;
+-----------------+
| Tables_in_seata |
+-----------------+
| account_tbl     |
| order_tbl       |
| storage_tbl     |
| undo_log        |
+-----------------+
4 rows in set (0.01 sec)

執行完之后,數據庫里應該有4個表

修改seata-samples/dubbo/src/main/resources/jdbc.properties文件

根據你MySQL運行的環境修改變量的值

jdbc.account.url=jdbc:mysql://localhost:3306/seata
jdbc.account.username=your_username
jdbc.account.password=your_password
jdbc.account.driver=com.mysql.jdbc.Driver
# storage db config
jdbc.storage.url=jdbc:mysql://localhost:3306/seata
jdbc.storage.username=your_username
jdbc.storage.password=your_password
jdbc.storage.driver=com.mysql.jdbc.Driver
# order db config
jdbc.order.url=jdbc:mysql://localhost:3306/seata
jdbc.order.username=your_username
jdbc.order.password=your_password
jdbc.order.driver=com.mysql.jdbc.Driver

ZooKeeper

啟動ZooKeeper,我的本地的Mac是使用Homebrew安裝啟動的

$ brew services start zookeeper 
==> Successfully started `zookeeper` (label: homebrew.m$ brew services list           
Name              Status  User    Plist
docker-machine    stopped         
elasticsearch     stopped         
kafka             stopped         
kibana            stopped         
mysql             started portman /Users/portman/Librar
y/LaunchAgents/homebrew.mxcl.mysql.plist
nginx             stopped         
postgresql        stopped         
redis             stopped         
zookeeper         started portman /Users/portman/Librar
y/LaunchAgents/homebrew.mxcl.zookeeper.plist

啟動TC事務協調器

在這個鏈接里頁面中,下載對應版本的seata-server程序,我本地下載的是1.2.0版本

  1. 進入文件所在目錄并解壓文件
  2. 進入seata目錄
  3. 執行啟動腳本
$ tar -zxvf seata-server-1.2.0.tar.gz
$ cd seata
$ bin/seata-server.sh

觀察啟動日志是否有報錯信息,如果一切正常,并看到了以下的Server started的信息,說明啟動成功了。

2020-07-23 13:45:13.810 INFO [main]io.seata.core.rpc.netty.RpcServerBootstrap.start:155 -Server started ...

IDE中啟動模擬的微服務

  1. 首先要把seata-samples項目導入到本地IDE中,這里我用的是IntelliJ IDEA
  2. 刷新Maven的工程依賴
  3. 先啟動Account,Order,Storage這個3個服務,然后Business才能去調用,對應的啟動類分別是:
io.seata.samples.dubbo.starter.DubboStorageServiceStarter
io.seata.samples.dubbo.starter.DubboOrderServiceStarter
io.seata.samples.dubbo.starter.DubboStorageServiceStarter

每個服務啟動完之后,看到這句提示信息,說明服務啟動成功了

Application is keep running ...

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

啟動成功后,account_tbl,storage_tbl表會有兩條初始化的數據,分別是賬戶余額和商品庫存

mysql> SELECT * FROM account_tbl; SELECT * FROM storage_tbl;
+----+---------+-------+
| id | user_id | money |
+----+---------+-------+
|  1 | U100001 |   999 |
+----+---------+-------+
1 row in set (0.00 sec)+----+----------------+-------+
| id | commodity_code | count |
+----+----------------+-------+
|  1 | C00321         |   100 |
+----+----------------+-------+
1 row in set (0.00 sec)

使用Business驗證效果

正常情況

還是在IDE中執行DubboBusinessTester類的主函數,程序跑完會自動退出

在程序一切正常的情況下,每個微服務的事物都應該是提交了的,數據保持一致

我們來看一下MySQL中數據的變化

mysql> SELECT * FROM account_tbl; SELECT * FROM order_tbl; SELECT * FROM storage_tbl;
+----+---------+-------+
| id | user_id | money |
+----+---------+-------+
|  1 | U100001 |   599 |
+----+---------+-------+
1 row in set (0.00 sec)+----+---------+----------------+-------+-------+
| id | user_id | commodity_code | count | money |
+----+---------+----------------+-------+-------+
|  1 | U100001 | C00321         |     2 |   400 |
+----+---------+----------------+-------+-------+
1 row in set (0.00 sec)+----+----------------+-------+
| id | commodity_code | count |
+----+----------------+-------+
|  1 | C00321         |    98 |
+----+----------------+-------+
1 row in set (0.00 sec)

從3個表的數據可以看到:賬戶余額扣減了400塊;訂單表增加了1條記錄;商品庫存扣減了2個

這個結果是程序的邏輯是一致的,說明事務沒有問題

異常情況

其實即使不加入分布式事務的控制,一切都正常情況下,事務本身就不會有問題的

所以我們來重點關注,當程序出現異常時的情況

現在我把BusinessServiceImpl的拋異常的代碼注釋放開,然后再執行一次DubboBusinessTester,來看看有什么情況發生

		@Override@GlobalTransactional(timeoutMills = 300000, name = "dubbo-demo-tx")public void purchase(String userId, String commodityCode, int orderCount) {LOGGER.info("purchase begin ... xid: " + RootContext.getXID());storageService.deduct(commodityCode, orderCount);orderService.create(userId, commodityCode, orderCount);//放開這句拋異常的注釋,模擬程序出現異常throw new RuntimeException("portman's foooooobar error.");}

接著,我再一次執行DubboBusinessTester,執行過程中在控制臺可以看到異常報錯信息

Exception in thread "main" java.lang.RuntimeException: portman's foooooobar error.

現在我們再看一下MySQL里的數據變化,發現數據沒有任何變化,說明分布式事務的控制已經起作用了

待思考問題

上面的步驟只是演示了seata最簡單的demo程序,更多更復雜的情況后續大家可以一起討論和驗證

學習過程中還有一些問題和疑惑,后續進一步學習

  • 全局鎖對性能的影響程度
  • undo_log日志可以回滾到原來狀態,但是如果數據狀態已經發生變化如何處理(比如增加的用戶積分已經被別的本地事務花掉了)

參考文獻

  • Seata 是什么?
  • 快速開始

作者信息

許曉加,金蝶軟件架構師

Github

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/42294.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/42294.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/42294.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Git教程

文章目錄 Git分布式版本控制工具版本控制器的方式常用命令遠程倉庫Tip Git分布式版本控制工具 ? Git是一個開源的分布式版本控制系統,可以有效、高速地處理從很小到非常大的項目版本管理。 ? Git是分布式的,Git不需要有中心服務器,我們每…

【感謝告知】本賬號內容調整,聚焦于Google賬號和產品的使用經驗和問題案例分析

親愛的各位朋友: 感謝您對本賬號的關注和支持! 基于對朋友們需求的分析和個人興趣的轉變,該賬號從今天將對內容做一些調整,有原來的內容改為Google(谷歌)賬號和產品的使用經驗,以及相關問題的…

24西安電子科技大學經濟與管理學院—考研錄取情況

24西安電子科技大學—經理與管理學院—考研錄取統計 01、經理與管理學院各個方向 02、24經濟與管理近三年復試分數線對比 1、經管院24年院線相對于23年院線普遍下降2-15分,個別專業上漲4-10分。 2、經管院應用經濟學2024年院線350分;管理科學與工程院線…

java join與yield方法

join() join() 方法的主要作用是使當前線程(調用 join() 方法的線程)等待目標線程完成執行。當目標線程執行完畢后,當前線程才會繼續執行。 代碼示例: public class JoinExample {public static void main(String[] args) {Thr…

保研復習 | 數據結構

目錄 CH1?緒論☆ 數據項、數據元素、數據結構☆ 邏輯結構和存儲結構的區別☆ 順序存儲結構和鏈式存儲結構的比較☆ 算法的重要特性☆ 算法的復雜度 CH2?線性表☆ 單鏈表 CH3?棧、隊列和數組☆ 棧和堆是什么?☆ 棧在括號匹配中的應用☆ 棧在表達式求值中的應用☆ …

Linux|信號

Linux|信號 信號的概念信號處理的三種方式捕捉信號的System Call -- signal 1.產生信號的5種方式2.信號的保存2.1 core 標志位 2.信號的保存2.1 對pending 表 和 block 表操作2.2 阻塞SIGINT信號 并打印pending表例子 捕捉信號sigaction 函數驗證當前正在處理某信號&#xff0c…

數據庫SQL Server常用字符串函數

文章目錄 字符串函數 字符串函數 CONCAT:拼接字符串 CONCAT(COLUMN1,_,COLUMN2) AS COLCONVERT:轉換數據類型 CONVERT(data_type(length),data_to_be_converted,style)例如:CONVERT(VARCHAR(10),GETDATE(),110) SUBSTRING():從字符串中返回…

java項目總結5

1.單列集合頂層接口Collction 集合體系結構 注意:因為Collection定義的方法是共性的,使用不能通過搜引來刪除,只能通過元素的對象進行刪除,返回值是boolean類型。例如我添加了"aaa"進List集合,刪除則要對象…

STM32-01 推挽輸出-點亮LED

本文以STM32中點亮LED為例,解讀推挽輸出的原理 推挽輸出介紹 所謂的推挽輸出,就是通過控制輸出控制模塊,打開或者關閉P-MOS或者N-MOS。 ─ 推挽模式下:輸出寄存器上的’0’激活N-MOS,而輸出寄存器上的’1’將激活P-M…

局部靜態變量實現的單例存在多個對象

文章目錄 背景測試代碼運行測試嘗試打開編譯器優化進一步分析 背景 業務中出現日志打印失效&#xff0c;發現是因為管理日志對象的單例在運行過程中存在了多例的情況。下面通過還原業務場景來分析該問題。 測試代碼 /* A.h */ #ifndef CALSS_A #define CALSS_A#include <…

打造屬于自己的腳手架工具并發布到npm倉庫

一、創建項目 使用 npm init -y 創建項目創建項目入口文件 index.js在 package.json 中添加 bin 字段使用 npm link 命令將文件映射至全局&#xff0c;使可以在本地測試 zp 命令 // "zp" 為用于全局執行腳手架的命令&#xff0c;vue-cli中使用的是vue命令 "bi…

pyecharts可視化案例大全(11~20)

pyecharts可視化案例大全(11~20) 十一、設置動畫效果十二、直方圖帶視覺組件十三、設置漸變色(線性漸變)十四、設置漸變色(徑向漸變)十五、設置分割線十六、設置分隔區域十七、面積圖十八、堆疊面積圖十九、自定義線樣式二十、折線圖平滑處理十一、設置動畫效果 在圖表加載前…

【AI原理解析】—主成分分析(PCA)原理

目錄 一、PCA的思想 二、PCA的步驟 三、關鍵概念 四、PCA的優勢與應用 PCA&#xff08;主成分分析&#xff0c;Principal Component Analysis&#xff09;是一種廣泛使用的數據降維算法&#xff0c;它通過線性變換將原始數據轉換為一組各維度線性無關的表示&#xff0c;從而…

iOS應用的內存優化

對一個 iOS 項目進行內存優化&#xff0c;可以從多個方面入手&#xff0c;確保應用在不同場景下都能高效穩定地運行。以下是一些具體的內存優化措施和詳細說明&#xff1a; 1. 自動引用計數&#xff08;ARC&#xff09;管理 1.1 避免循環引用 循環引用會導致內存泄漏。使用 …

低代碼平臺的設計模式介紹

低代碼平臺是一種快速交付應用程序的開發工具&#xff0c;主要通過圖形拖拽用戶界面、應用配置界面&#xff0c;使開發者能夠以最少的手動編碼&#xff0c;或者不需要代碼快速交付應用。這種平臺的核心優勢在于提高開發速度和降低技術門檻&#xff0c;使得非技術背景的用戶也能…

基于java+springboot+vue實現的旅游管理系統(文末源碼+lw+ppt)23-402

研究的內容 當下流行的WPS、Word等辦公軟件成為了人們耳熟能詳的系統&#xff0c;但一些更加專業性、性能更加強大的網絡信息工具被人們“埋沒”在互聯網的大海中。甘肅旅游管理系統是一個便于用戶查看熱門景點、酒店信息、推薦線路、旅游攻略、景點資訊等&#xff0c;管理員進…

【Python基礎篇】你了解python中運算符嗎

文章目錄 1. 算數運算符1.1 //整除1.2 %取模1.3 **冪 2. 賦值運算符3. 位運算符3.1 &&#xff08;按位與&#xff09;3.2 |&#xff08;按位或&#xff09;3.3 ^&#xff08;按位異或&#xff09;3.4 ~&#xff08;按位取反&#xff09;3.5 <<&#xff08;左移&#…

HTML 【實用教程】(2024最新版)

核心思想 —— 語義化 【面試題】如何理解 HTML 語義化 ?僅通過標簽便能判斷內容的類型&#xff0c;特別是區分標題、段落、圖片和表格 增加代碼可讀性&#xff0c;讓人更容易讀懂對SEO更加友好&#xff0c;讓搜索引擎更容易讀懂 html 文件的基本結構 html 文件的文件后綴為 …

【高錄用、快檢索、過往5屆均已檢索、SPIE 出版】第六屆無線通信與智能電網國際會議(ICWCSG 2024)

隨著科技的飛速發展和能源需求的日益增長&#xff0c;智能電網技術逐漸成為電力行業的重要發展方向。與此同時&#xff0c;無線通信技術在近年來也取得了顯著的進步&#xff0c;為智能電網的發展提供了強有力的支持。為了進一步推動無線通信與智能電網的結合與發展&#xff0c;…

Vue3 對于內嵌Iframe組件進行緩存

1&#xff1a;應用場景 對于系統內所有內嵌iframe 的頁面均通過同一個路由/iframe, 在router.query內傳入不同src 參數&#xff0c;在同一組件內顯示iframe 內嵌頁面&#xff0c;對這些頁面分別進行緩存。主要是通過v-show 控制顯示隱藏從而達到iframe 緩存邏輯 2&#xff1a…