SpringCloud Alibaba之Seata入門以及踩坑(二)

前言

上一篇文章:➣SpringCloud Alibaba之Seata入門以及踩坑(一)老顧介紹了seata相關的準備工作,以及版本的選擇;今天老顧就來介紹一下seata的使用。以及在使用過程中遇到的問題。

案例背景

今天老顧介紹的案例場景也就是網上常用的場景,用戶下單場景。整個流程就是用戶下單時:

1)創建訂單,訂單狀態爲創建中

2)扣減商品庫存

3)扣減用戶金額

4)更改訂單狀態,訂單狀態爲已完結

從以上業務流程,我們可以分爲3個服務,如圖

因爲上面是3個分佈式服務,事務問題就由此產生,我們來看看seata怎麼來解決?

Client端準備

上文中已經介紹了seata-server的準備工作,需要首先啓動seata服務。下面我們來看看client端項目需要做什麼準備。

項目依賴

我們需要在項目中引入seata的jar包,有以下選擇(任選其一):

  • 依賴seata-all 手動配置較多
  • 依賴seata-spring-boot-starter,支持yml配置
  • 依賴spring-cloud-starter-alibaba-seata,內部集成了seata,並實現了xid傳遞

注意:client 版本與 server端版本一致

上面三種方式,需要做不同的事情,尤其xid的傳遞是比較麻煩的,還好spring-cloud-starter-alibaba-seata已經幫我們實現,具體看看下圖:

這裏我們就用spring-cloud-starter-alibaba-seata方式。

因爲我們seata-server用了1.3.0,所以我們client也需要同一版本。

數據庫準備

3個微服務rb-order-server、rb-account-server、rb-storage-server我們就創建3個數據庫。

seata-order庫中創建t_order

seata-account庫中創建t_account

seata_storage庫中創建t_storage

項目新建undo_log表

每個微服務項目有獨立的數據庫,則需要在庫中創建undo_log表

微服務項目中引入mybatis-plus操作數據庫,這裏老顧就不介紹了。

微服務配置

我們聚焦到seata相關上面;上文中我們seata-server服務是結合nacos的。

我們在rb-order-server、rb-account-server、rb-storage-server3個服務的application.yml配置文件中,都要配置相關seata的配置。

上面的配置比較容易理解,有幾個地方很重要:

1)enable-auto-data-source-proxy

這個配置就是啓動自動開啓數據源代理。

2)tx-service-group:seata_test_tx_group

這個是事務分組,項目的微服務都要配置一樣的事務分組,並且要和上文中的seata-server的service.vgroupMapping.seata_test_tx_group=default一致。

數據庫代理

因爲seata採用了DataSource代理方式操作數據,所以在springboot項目中先要排除datasource初始化,這樣yml文件中的seata.enable-auto-data-source-proxy: true 自動代理纔會生效。如何排除也是比較簡單,三個服務都要排除,啓動自動數據庫代理。

以上client準備工作就結束了。

Feign調用

因爲order服務中要調用account服務、storage服務,所以order中需要引入feign調用,如果把三個服務加入註冊中心,能夠互動調用;老顧這裏就不介紹了,小夥伴們可以看老顧的以前的文章。

我們在來看看各個服務的具體實現。

項目服務代碼

庫存服務

上面的代碼,能夠發現如果下單的時候超過庫存數,就會拋異常;

用戶服務

上面的代碼,如果扣減的金額超過用戶金額時,就拋異常;

訂單服務

上面的訂單服務代碼中,我們發現引入了@GlobalTransactional;對的,就是加入了@GlobalTransactional這個註解,就實現了分佈式事務,簡單吧。

我們可以啓動postman,請求count參數爲1的話,查看業務數據庫數據都正常。對應的庫存減少了1,金額減少了100,訂單成功插入。

如果我們傳入的count參數大於庫存數,庫存服務就會拋異常,那庫存服務就會執行失敗,這樣訂單服務,用戶服務也會回滾。這樣就起到了分佈式事務作用。

感覺到這裏,小夥伴們是不是感覺seata的強大,這個就是seata推薦的AT模式。

Feign降級坑

在我們微服務使用中,一旦微服務產生異常,我們都會用到降級的功能;如在調用庫存服務的時候引入sentinel降級,這個知識老顧之前就介紹過,小夥伴們可以查看之前的文章。

spring:
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080
feign:
  sentinel:
    enabled: true

這樣對庫存服務的降級處理是實現了,這也是正常的微服務的使用。

但是這樣的處理,seata就會失效;我們發現count參數大於庫存時,庫存服務報異常,但因爲有降級處理,訂單還是提交了訂單數據,用戶金額還是減少了。事務不起作用了。

解決方式

官方推薦的方法,就是利用aop方式,手動處理全局事務回滾,我們在庫存服務中加入aop

從上述代碼中,我們用容易發現,如果執行的service中出現異常,就手動實現全局事務rollback。這樣就解決了Feign的降級的問題。

注意:上面的aop代碼中,before、after方法中,可以結合自身的業務 本案例中庫存服務,只在拋異常的時候做了處理

總結

seata的分佈式事務使用起來是非常簡單的,但是seata的使用會對現有項目中產生一些意外的錯誤,但是都可以得到相應的解決;需要小夥伴去實踐。謝謝!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章