自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

解決分布式事務(wù),Seata真香!

開發(fā) 后端
既然要給大家講什么是 seata,那就得先說一下這個(gè)東西的定位,這東西就是現(xiàn)在很火的 Spring Cloud Alibaba 里的一個(gè)組件,是專門幫助我們解決分布式事務(wù)問題的,也就是說,seata 是一個(gè)分布式事務(wù)框架。

背景

大家好,今天給大家分享一個(gè)在 2022 年出去面試 Java 幾乎必問的一個(gè)技術(shù),那就是 seata。

什么??你才看了第一句話心里有閃現(xiàn)了無數(shù)個(gè)問號(hào)?因?yàn)闆]聽說過 seata 這個(gè)東西?

沒關(guān)系,為了避免兄弟們出去面試被問到 seata 的時(shí)候,一臉蒙圈,我們今天就把這個(gè)東西給大家講明白。

既然要給大家講什么是 seata,那就得先說一下這個(gè)東西的定位,這東西就是現(xiàn)在很火的 Spring Cloud Alibaba 里的一個(gè)組件,是專門幫助我們解決分布式事務(wù)問題的,也就是說,seata 是一個(gè)分布式事務(wù)框架。

什么是分布式事務(wù)

那可能很多小伙伴很蒙圈了,什么是分布式事務(wù)?好吧,為了保證大家能繼續(xù)看下去,我們先說一下什么是分布式事務(wù)這個(gè)問題。

舉個(gè)最簡(jiǎn)單的例子,假設(shè)現(xiàn)在你負(fù)責(zé)了一個(gè)訂單系統(tǒng),一個(gè)庫(kù)存系統(tǒng),一個(gè)營(yíng)銷系統(tǒng),然后呢,當(dāng)你的訂單系統(tǒng)收到用戶一個(gè)請(qǐng)求要?jiǎng)?chuàng)建訂單的時(shí)候,這個(gè)時(shí)候你得做三件事情。

第一,調(diào)用庫(kù)存系統(tǒng)的接口鎖定庫(kù)存,第二,調(diào)用調(diào)用營(yíng)銷系統(tǒng)的接口鎖定優(yōu)惠券,第三,你訂單系統(tǒng)自己得在 MySQL 里插入一系列訂單的數(shù)據(jù)。

比如下圖 1 所示:

那么現(xiàn)在問題來了,你訂單系統(tǒng)有自己的訂單數(shù)據(jù)庫(kù),可以去插入訂單數(shù)據(jù),那庫(kù)存系統(tǒng)是不是也應(yīng)該有自己的庫(kù)存數(shù)據(jù)庫(kù),去鎖定庫(kù)存數(shù)據(jù)?

營(yíng)銷系統(tǒng)是不是應(yīng)該有自己的營(yíng)銷數(shù)據(jù)庫(kù),去鎖定優(yōu)惠券?當(dāng)然是了!每個(gè)人都有自己的數(shù)據(jù)庫(kù),這一個(gè)都不能少。

如下圖 2 所示:

那現(xiàn)在問題又來了,既然一次創(chuàng)建訂單的請(qǐng)求,要涉及到訂單、庫(kù)存、營(yíng)銷三個(gè)系統(tǒng),分別操作各自自己的三個(gè)數(shù)據(jù)庫(kù),才能完成這次請(qǐng)求。

那是不是可能會(huì)出現(xiàn)這么一種情況,首先呢,你先調(diào)用庫(kù)存系統(tǒng),鎖定了庫(kù)存了,O 了。

接著呢,你又調(diào)用了營(yíng)銷系統(tǒng),鎖定了優(yōu)惠券,也 O 了。最后呢,當(dāng)你訂單系統(tǒng)要往自己的訂單數(shù)據(jù)庫(kù)里插入數(shù)據(jù)的時(shí)候,網(wǎng)絡(luò)抽風(fēng)了,導(dǎo)致你這一次插入訂單數(shù)據(jù)失敗了,直接 exception 異常了,你蒙圈了。

如下圖 3 所示:

那這個(gè)時(shí)候你覺得可能會(huì)產(chǎn)生什么樣的問題呢,其實(shí)很簡(jiǎn)單,這個(gè)時(shí)候你這個(gè)訂單要購(gòu)買的商品庫(kù)存已經(jīng)被鎖定了,你為了下這個(gè)訂單用的優(yōu)惠券,也已經(jīng)被鎖定了。

結(jié)果呢,你的訂單自己本身的數(shù)據(jù)并沒進(jìn)入數(shù)據(jù)庫(kù),然后還返回一個(gè)了異常信息給用戶說,本次下單失敗。

但是你說下單失敗就失敗吧,結(jié)果呢,運(yùn)營(yíng)看庫(kù)存數(shù)據(jù)的時(shí)候可能會(huì)一臉蒙圈,為啥有一些商品庫(kù)存被鎖定了,結(jié)果沒有對(duì)應(yīng)的跟訂單,而且一直沒人付款來購(gòu)買呢??

然后用戶自己也有點(diǎn)發(fā)蒙,因?yàn)橐徊樽约旱膬?yōu)惠券,好不容易攢了幾張券來買東西,結(jié)果現(xiàn)在訂單沒下成,優(yōu)惠券狀態(tài)都搞成已使用了,自己還沒法用這些優(yōu)惠券了。

如下圖 4 所示:

其實(shí)這就是一個(gè)非常經(jīng)典的分布式事務(wù)的問題了,你一個(gè)創(chuàng)建訂單的請(qǐng)求,橫跨了訂單、庫(kù)存、營(yíng)銷三個(gè)系統(tǒng),分別涉及三個(gè)數(shù)據(jù)庫(kù)。

所有很可能會(huì)發(fā)現(xiàn),你的庫(kù)存和營(yíng)銷的數(shù)據(jù)操作都成功了,而且?guī)齑婧蜖I(yíng)銷數(shù)據(jù)庫(kù)里的本地事務(wù)都提交了,結(jié)果訂單插入數(shù)據(jù)庫(kù)失敗了,訂單數(shù)據(jù)庫(kù)里的本地事務(wù)回滾了,但是庫(kù)存和營(yíng)銷數(shù)據(jù)庫(kù)里的本地事務(wù)已經(jīng)提交了,他們是不會(huì)回滾的。

如下圖 5 所示:

什么叫做逆向補(bǔ)償

那既然問題已經(jīng)找到了,我們希望的應(yīng)該是什么效果呢?

我們其實(shí)希望的效果是,如果訂單要是插入數(shù)據(jù)庫(kù)失敗了,訂單數(shù)據(jù)庫(kù)本地事務(wù)回滾了,我們應(yīng)該想辦法去通知一下庫(kù)存系統(tǒng)和營(yíng)銷系統(tǒng),把之前在庫(kù)存數(shù)據(jù)庫(kù)和營(yíng)銷數(shù)據(jù)庫(kù)里已經(jīng)提交的數(shù)據(jù)修改做一個(gè)逆向補(bǔ)償,進(jìn)行恢復(fù)。

什么叫做逆向補(bǔ)償呢?意思就是說,之前庫(kù)存系統(tǒng)如果在數(shù)據(jù)庫(kù)里執(zhí)行的是 insert,那么此時(shí)就應(yīng)該執(zhí)行 delete,把之前插入的數(shù)據(jù)刪除了。

如果之前執(zhí)行的 delete,現(xiàn)在就應(yīng)該執(zhí)行 insert,把刪除的額數(shù)據(jù)重新插入回去,如果之前執(zhí)行的是 udpate 語句,現(xiàn)在就應(yīng)該再次執(zhí)行一個(gè) update 語句,把數(shù)據(jù)恢復(fù)到更新之前的狀態(tài)。

如下圖 6 所示:

互聯(lián)網(wǎng)最流行的分布式事務(wù)組件 seata

那既然我們想要實(shí)現(xiàn)這個(gè)效果,這個(gè)時(shí)候問題就來了,單單依賴我們自己那肯定搞不定這個(gè)問題了,這個(gè)時(shí)候就必須引入 Spring Cloud Alibaba 里的大佬組件,seata。

seata 就是專門幫助我們解決這個(gè)問題的,如果我們要是在系統(tǒng)里引入 seata 框架之后,其實(shí)每個(gè)系統(tǒng)里都會(huì)嵌入 seata,同時(shí)我們還需要去部署一個(gè) seata server。

如下圖 7 所示:

這個(gè)時(shí)候,我們的系統(tǒng)運(yùn)行原理會(huì)變成這樣:訂單系統(tǒng)中的 seata 會(huì)發(fā)送請(qǐng)求給 seata server 去開啟一個(gè)全局事務(wù),然后庫(kù)存系統(tǒng)先運(yùn)行,他在進(jìn)行數(shù)據(jù)庫(kù) crud 的時(shí)候,這些操作都會(huì)被 seata 框架進(jìn)行攔截。

然后 seata 框架會(huì)在一個(gè)本地事務(wù)里,把你的 sql 語句和逆向補(bǔ)償日志,一起插入到你的庫(kù)存數(shù)據(jù)庫(kù)里去,在庫(kù)存數(shù)據(jù)庫(kù)里必須有一個(gè) undo_log 表,存儲(chǔ) seata 的逆向補(bǔ)償日志。

那這個(gè)逆向補(bǔ)償日志是什么呢?簡(jiǎn)單,如果你的 sql 是 insert,那逆向補(bǔ)償日志可以幫助你后續(xù)構(gòu)建 delete 語句來刪除,如果你的 sql 是 update,那逆向補(bǔ)償日志可以記錄你更新之前的舊數(shù)據(jù),他可以幫助你后續(xù)把數(shù)據(jù) update 到老版本的狀態(tài)。

如下圖 8 所示:

你庫(kù)存系統(tǒng)的 sql 語句和他們的補(bǔ)償日志,是在一個(gè)本地事務(wù)里一起提交的,一起成功或者一起失敗,所以但凡你的庫(kù)存系統(tǒng)更新成功了,就一定會(huì)有對(duì)應(yīng)的補(bǔ)償日志也會(huì)在庫(kù)存 數(shù)據(jù)庫(kù)里的,以備不時(shí)之需,營(yíng)銷系統(tǒng)其實(shí)也是相同的運(yùn)行原理。

那么假設(shè)說庫(kù)存系統(tǒng)和營(yíng)銷系統(tǒng),按照這個(gè)思路都執(zhí)行完畢了,到訂單系統(tǒng)了,他結(jié)果撂挑子了,插入訂單數(shù)據(jù)庫(kù)失敗。

當(dāng)然,在插入的時(shí)候其實(shí)也會(huì)有對(duì)應(yīng)的補(bǔ)償日志會(huì)一起提交,但是因?yàn)檫@個(gè)時(shí)候網(wǎng)絡(luò)問題,導(dǎo)致插入訂單和插入補(bǔ)償日志一起失敗了。

所以此時(shí)訂單系統(tǒng)的 seata 就會(huì)上報(bào) seata server 說,大哥,我這兒完?duì)僮恿?,您要不通知?kù)存和營(yíng)銷兩個(gè)兄弟,逆向補(bǔ)償一下吧。

如下圖 9 所示:

接著 seata server 發(fā)現(xiàn)說,這分布式事務(wù)都失敗了,那趕緊的,他會(huì)通知庫(kù)存系統(tǒng)和營(yíng)銷系統(tǒng)里的 seata 框架小兄弟說,兄弟們,趕緊的,把之前插入你們數(shù)據(jù)庫(kù)里的 undo_log 表里的補(bǔ)償日志拿出來,構(gòu)建一下逆向補(bǔ)償 sql。

之前是 insert 你就給我弄個(gè) delete,之前是 delete 你就給我弄個(gè) insert,之前是 update 你還是 update,逆向補(bǔ)償 sql 趕緊跑一把,把數(shù)據(jù)給我恢復(fù)了,前隊(duì)改后隊(duì),跑步前進(jìn),hurry up 起來。

如下圖 10 所示:

總結(jié)

太棒了,到這個(gè)時(shí)候?yàn)橹梗覀兙桶l(fā)現(xiàn) seata 老大的作用了,你訂單、庫(kù)存、營(yíng)銷三個(gè)系統(tǒng)隨便跑,有誰失敗了,seata server 收到你的失敗通知,就會(huì)告訴別的系統(tǒng)用 undo log 日志構(gòu)建補(bǔ)償 sql,把數(shù)據(jù)都給回滾了,完美。

責(zé)任編輯:姜華 來源: 石杉的架構(gòu)筆記
相關(guān)推薦

2024-10-09 14:14:07

2022-01-12 10:02:02

TCC模式 Seata

2022-06-27 08:21:05

Seata分布式事務(wù)微服務(wù)

2022-06-21 08:27:22

Seata分布式事務(wù)

2025-04-28 00:44:04

2020-12-09 09:14:57

SpringCloudSeata 分布式

2022-07-10 20:24:48

Seata分布式事務(wù)

2025-01-26 00:00:40

Seata分布式事務(wù)

2021-04-23 08:15:51

Seata XA AT

2023-11-06 13:15:32

分布式事務(wù)Seata

2024-08-19 09:05:00

Seata分布式事務(wù)

2023-01-06 09:19:12

Seata分布式事務(wù)

2022-07-03 14:03:57

分布式Seata

2023-08-17 10:23:07

擴(kuò)展方案

2020-12-08 11:43:03

Spring Clou分布式Seata

2024-12-02 09:19:44

2025-04-29 04:00:00

分布式事務(wù)事務(wù)消息

2022-10-26 17:28:41

分布式事務(wù)seata

2022-06-14 10:47:00

分布式事務(wù)數(shù)據(jù)

2021-08-06 08:33:27

Springboot分布式Seata
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)