分布式事務seata


  在我面試招行外包的時候,與三位面試官進行了半個多小時的交鋒,從java基礎到框架,其中讓我記憶深刻的有一個問題。我說到我們系統采用了微服務架構,是根據不同崗位划分成幾個服務,服務之間的調用是用openFeign。A服務減庫存並調用B服務增加相應庫存,使用事務管理防止操作失敗。

面試官:等一下,你說一下事務有什么特性?

我:事務有四個特性,原子性、一致性、隔離性、額還有一個忘了(我太緊張了)

面試官:那你大概解釋一下每個特性

我:原子性就是事務要么全部成功要么全部失敗,一致性就是事務執行前和執行后是一致的,假設A和B共100塊錢,無論怎么相互轉賬,總共還是100塊錢,

隔離性就是每個事務之間是相互隔離不影響的,(補充:持久性就是事務一旦提交了,對數據庫的改變就是永久性的)

面試官: 事務的隔離級別有幾種

我:巴拉巴拉。。。

事務隔離級別 臟讀 不可重復讀 幻讀
讀未提交(read-uncommitted)
不可重復讀(read-committed)
可重復讀(repeatable-read)
串行化(serializable)

面試官: 你是怎么保證數據不出錯的

我:通過事務管理(我指的是spring本地事務,我還不知道分布式事務),如果有異常則數據回滾,B服務的方法執行完之后,校驗數據是否插入成功,如果沒有插入成功則手動拋出異常。

面試官:如果網絡延遲B服務沒有及時插入,或者其他原因導致你校驗的時候B數據庫並沒有插入數據,但是隨后又插入成功了,這種情況你是如何解決的

我:。。。(我就此被KO了)

 

  過后我才了解到分布式事務這種東西,一個很經典的場景,在微服務架構中,訂單服務下訂單,就要調用庫存服務減庫存,如果庫存不足,就下單失敗。常見的分布式事務類型有 2PC、3PC、TCC、本地消息表、消息事務、最大努力通知,對於這幾種我在此先不講了,給大家推薦一篇我很喜歡的博主(敖丙)的文章,他寫的很好,我經常看他的文章,https://zhuanlan.zhihu.com/p/183753774,我今天就只談一下阿里開源的分布式事務框架Seata,Seata 是 Simple Extensible Autonomous Transaction Architecture 的簡寫,詳細介紹可參考官網https://seata.io/zh-cn/還有在碼雲上的倉庫https://gitee.com/itCjb/spring-cloud-alibaba-seata-demo里面有示例代碼和相關文檔。這些東西我覺得沒必要寫了,我寫的不一定有大佬和官方寫的好,所以我就分享一下我在安裝部署使用中碰到的一些坑:

1、安裝seata服務端並注冊到nacos(我是放在阿里雲ECS上面)

  簡單粗暴的方法就是到seata的gitbub上去下載linux版本的壓縮包,我就是是這樣的,或者其他途徑也行,然后通過工具上傳到服務器,解壓,啟動就完事了,但是這樣是不行的,需要改配置才能成功連接數據庫和注冊到nacos

file.conf (在conf文件夾里)

 

 1 ## transaction log store, only used in seata-server
 2 store {
 3   ## store mode: file、db、redis
 4   mode = "db"
 5 
 6   ## database store property
 7   db {
 8     ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
 9     datasource = "druid"
10     ## mysql/oracle/postgresql/h2/oceanbase etc.
11     dbType = "mysql"
12     driverClassName = "com.mysql.jdbc.Driver"
13     url = "jdbc:mysql://127.0.0.1:3306/seata"
14     user = "root"
15     password = "123456"
16     minConn = 5
17     maxConn = 30
18     globalTable = "global_table"
19     branchTable = "branch_table"
20     lockTable = "lock_table"
21     queryLimit = 100
22     maxWait = 5000
23   }
24 }

這是我的配置,默認配置里還有redis和file模式的默認配置,我沒用到就刪掉了,這個文件只需要修改幾個地方,其余的用默認的就行,如果有興趣可以自行研究。

 

1 # 這個改成自己的數據庫類型,注意是seata要連接的數據庫,不是業務數據庫
2 dbType = "mysql"
3 # 數據庫驅動,根據自己的數據庫及版本選擇
4 driverClassName = "com.mysql.jdbc.Driver"
5 # 數據源配置(懂的都懂),需要自己先建這個庫,然后導入官方提供的sql腳本
6 url = "jdbc:mysql://127.0.0.1:3306/seata"
7 user = "root"
8 password = "123456"

相關sql腳本,可以到看官方文檔,我就不貼了,如果以后更新了貼了可能還會誤導,我盡量避免版本更新了我這篇文章就白寫了。然后還需要在每個參與全局事務的數據庫中加入undo_log表,這是用來存儲事務回滾所需的一些數據。

第二步就是修改config.txt文件並添加到nacos

 

 1 # my_test_tx_group 可以根據自定義,多個服務可以配置多個
 2 service.vgroupMapping.my_test_tx_group=default
 3 # 因為我的數據庫也是在ECS上,所以IP是127.0.0.1,這里與上一步幾乎一樣
 4 store.mode=db
 5 store.db.datasource=druid
 6 store.db.dbType=mysql
 7 store.db.driverClassName=com.mysql.jdbc.Driver
 8 store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true
 9 store.db.user=root
10 store.db.password=123456
11 # 以下配置我沒動,采用默認配置 you can you do
12 store.db.minConn=5
13 store.db.maxConn=30
14 store.db.globalTable=global_table
15 store.db.branchTable=branch_table
16 store.db.queryLimit=100
17 store.db.lockTable=lock_table
18 store.db.maxWait=5000

改完之后可以用官方提供的腳本nacos-config.sh將配置添加到nacos配置中心,如果無聊也可以自己一個一個添加

第三步,修改registry.conf

 

 1 registry {
 2   # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
 3   # 類型選nacos
 4   type = "nacos"
 5   nacos {
 6     # 應用名默認
 7     application = "seata-server"
 8     # IP 我改成我服務器IP
 9     serverAddr = "127.0.0.1:8848"
10     # 分組就默認,注意:需要參與全局事務的服務都要跟seata-server在同一個命名空間同一個分組
11     group = "SEATA_GROUP"
12     # 我是全部放在自己建的test空間,若沒有配置新的命名空間則默認就行
13     namespace = ""
14     cluster = "default"
15     username = "nacos"
16     password = "nacos"
17   }
18 }
19 # 下面配置也一樣的,不然無法讀取在nacos配置中心的配置
20 config {
21   # file、nacos 、apollo、zk、consul、etcd3
22   # 類型選nacos
23   type = "nacos"
24   nacos {
25     serverAddr = "127.0.0.1:8848"
26     namespace = ""
27     group = "SEATA_GROUP"
28     username = "nacos"
29     password = "nacos"
30   }
31 }

  到此seata服務端就安裝成功,然后就可以啟動seata-server,但是直接使用下面第一個命令啟動的話,會有2個問題,一個是關閉終端服務及關閉,二是本地服務會連接不上服務端,因為沒有指定IP的話,默認是內網IP,需要改成服務器IP,最好也定一下端口,然后加上其他命令后台啟動+后台運行

注意:阿里雲服務器的話需要在安全組新增策略開放8091端口,並在內部防火牆開通8091端口或者關閉內部防火牆

 

1 # 12 ./seata-server.sh
3 # 2、將日志輸出到nohup.out文件中
4 sudo nohup ./seata-server.sh  -p 8091 -h xxxxxxxxx >nohup.out 2>1 &

然后就可以登錄nacos查看seata-server是否啟動並注冊成功

 

 

2、配置seata客戶端

客戶端就簡單了,只需三步,添加依賴,添加配置,添加注解

添加依賴(至於版本可以根據官方推薦自行選擇)

 

 1         <dependency>
 2             <groupId>com.alibaba.cloud</groupId>
 3             <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
 4             <version>2.2.2.RELEASE</version>
 5             <exclusions>
 6                 <exclusion>
 7                     <groupId>io.seata</groupId>
 8                     <artifactId>seata-spring-boot-starter</artifactId>
 9                 </exclusion>
10             </exclusions>
11         </dependency>
12         <dependency>
13             <groupId>io.seata</groupId>
14             <artifactId>seata-spring-boot-starter</artifactId>
15             <version>1.3.0</version>
16         </dependency>    

添加配置

 

 1 seata:
 2   enabled: true
 3   # 我直接用服務名
 4   application-id: user-service
 5   # 這個就是 service.vgroupMapping.my_test_tx_group=default 中的my_test_tx_group 我也用服務名,這2個要一致
 6   tx-service-group: user-service
 7   enable-auto-data-source-proxy: true
 8   config:
 9     type: nacos
10     nacos:
11       namespace: ""
12       serverAddr: 127.0.0.1:8848
13       group: SEATA_GROUP
14       username: "nacos"
15       password: "nacos"
16   registry:
17     type: nacos
18     nacos:
19       application: seata-server
20       server-addr: 127.0.0.1:8848
21       group: SEATA_GROUP
22       namespace: “”
23       username: "nacos"
24       password: "nacos"

添加注解

1     @GlobalTransactional
2     @Override
3     public Result publish(Article article) {
4 
5         articleMapper.insert(article);
6         userFeign.updatePublishNum(article.getAuthor());
7         return null;
8     }
注意:如果采用本地事務@Transactional,insert方法執行成功,調用user-service有問題的話,article是沒法回滾的,這就需要使用分布式事務

  seata目前官方提供四種模式,我使用的是最便捷的AT模式,TCC、Saga、XA模式,you can you do,還有所有的服務,包括seata-server一定要在nacos的同一個空間同一個分組

    最后,碼字不容易,用你發財的小手點個贊吧,歡迎志同道合的同志,有什么問題或者意見,可以評論私信或者加我的企鵝群876083754(海綿寶寶的菠蘿屋)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM