微服務(wù)數(shù)據(jù)一致性解決方案

眾所周知拼缝,微服務(wù)架構(gòu)解決了很多問題,通過分解復(fù)雜的單體式應(yīng)用瓷炮,在功能不變的情況下,使應(yīng)用被分解為多個(gè)可管理的服務(wù)递宅,為采用單體式編碼方式很難實(shí)現(xiàn)的功能提供了模塊化的解決方案娘香。同時(shí),每個(gè)微服務(wù)獨(dú)立部署办龄、獨(dú)立擴(kuò)展烘绽,使得持續(xù)化集成成為可能。由此俐填,單個(gè)服務(wù)很容易開發(fā)安接、理解和維護(hù)。

微服務(wù)架構(gòu)為開發(fā)帶來了諸多好處的同時(shí)英融,也引發(fā)了很多問題赫段。比如服務(wù)運(yùn)維變得更復(fù)雜呀打,服務(wù)之間的依賴關(guān)系更復(fù)雜,數(shù)據(jù)一致性難以保證糯笙。

本篇文章將討論和介紹Choerodon豬齒魚是如何保障微服務(wù)架構(gòu)的數(shù)據(jù)一致性的。

主要內(nèi)容包括 :

  • 傳統(tǒng)應(yīng)用使用本地事務(wù)保持一致性
  • 多數(shù)據(jù)源下的分布式事務(wù)
  • 微服務(wù)架構(gòu)中應(yīng)滿足數(shù)據(jù)最終一致性原則
  • 使用Event Sourcing保證微服務(wù)的最終一致性
  • 使用可靠事件模式保證微服務(wù)的最終一致性
  • 使用Saga保證微服務(wù)的最終一致性

下面將通過一個(gè)實(shí)例來分別介紹這幾種模式撩银。

在Choerodon 豬齒魚的 DevOps流程中给涕,有這樣一個(gè)步驟。

  1. 用戶在Choerodon 平臺上創(chuàng)建一個(gè)項(xiàng)目额获;
  2. DevOps 服務(wù)對應(yīng)創(chuàng)建一個(gè)項(xiàng)目够庙;
  3. DevOps 為該項(xiàng)目 在 Gitlab 上創(chuàng)建對應(yīng)的group。

傳統(tǒng)應(yīng)用使用本地事務(wù)保持一致性

在講微服務(wù)架構(gòu)的數(shù)據(jù)一致性之前抄邀,先介紹一下傳統(tǒng)關(guān)系型數(shù)據(jù)庫是如何保證一致性的耘眨,從關(guān)系型數(shù)據(jù)庫中的ACID理論講起。

ACID 即數(shù)據(jù)庫事務(wù)正確執(zhí)行的四個(gè)基本要素境肾。分別是:

  • 原子性(Atomicity):要么全部完成剔难,要么全部不完成,不存在中間狀態(tài)
  • 一致性(Consistency):事務(wù)必須始終保持系統(tǒng)處于一致的狀態(tài)
  • 隔離性(Isolation):事務(wù)之間相互隔離奥喻,同一時(shí)間僅有一個(gè)請求用于同一數(shù)據(jù)
  • 持久性(Durability):事務(wù)一旦提交偶宫,該事務(wù)對數(shù)據(jù)庫所作的更改便持久的保存在數(shù)據(jù)庫之中,并不會被回滾

可以通過使用數(shù)據(jù)庫自身的ACID Transactions环鲤,將上述步驟簡化為如下偽代碼:

transaction.strat();
createProject();
devopsCreateProject();
gitlabCreateGroup();
transaction.commit();

這個(gè)過程可以說是十分簡單纯趋,如果在這一過程中發(fā)生失敗,例如DevOps創(chuàng)建項(xiàng)目失敗冷离,那么該事務(wù)做回滾操作吵冒,使得最終平臺創(chuàng)建項(xiàng)目失敗。由于傳統(tǒng)應(yīng)用一般都會使用一個(gè)關(guān)系型數(shù)據(jù)庫西剥,所以可以直接使用 ACID transactions痹栖。 保證了數(shù)據(jù)本身不會出現(xiàn)不一致。為保證一致性只需要:開始一個(gè)事務(wù)蔫耽,改變(插入结耀,刪除,更新)很多行匙铡,然后提交事務(wù)(如果有異常時(shí)回滾事務(wù))图甜。

隨著業(yè)務(wù)量的不斷增長,單數(shù)據(jù)庫已經(jīng)不足以支撐龐大的業(yè)務(wù)數(shù)據(jù)鳖眼,此時(shí)就需要對應(yīng)用和數(shù)據(jù)庫進(jìn)行拆分黑毅,于此同時(shí),也就出現(xiàn)了一個(gè)應(yīng)用需要同時(shí)訪問兩個(gè)或者兩個(gè)以上的數(shù)據(jù)庫或多個(gè)應(yīng)用分別訪問不同的數(shù)據(jù)庫的情況钦讳,數(shù)據(jù)庫的本地事務(wù)則不再適用矿瘦。

為了解決這一問題枕面,分布式事務(wù)應(yīng)運(yùn)而生。

多數(shù)據(jù)源下的分布式事務(wù)

想象一下缚去,如果很多用戶同時(shí)對Choerodon 平臺進(jìn)行創(chuàng)建項(xiàng)目的操作潮秘,應(yīng)用接收的流量和業(yè)務(wù)數(shù)據(jù)劇增。一個(gè)數(shù)據(jù)庫并不足以存儲所有的業(yè)務(wù)數(shù)據(jù)易结,那么我們可以將應(yīng)用拆分成IAM服務(wù)和DevOps服務(wù)枕荞。其中兩個(gè)服務(wù)分別使用各自的數(shù)據(jù)庫,這樣的情況下搞动,我們就減輕了請求的壓力和數(shù)據(jù)庫訪問的壓力躏精,兩個(gè)分別可以很明確的知道自己執(zhí)行的事務(wù)是成功還是失敗。但是同時(shí)在這種情況下鹦肿,每個(gè)服務(wù)都不知道另一個(gè)服務(wù)的狀態(tài)矗烛。因此,在上面的例子中箩溃,如果當(dāng)DevOps創(chuàng)建項(xiàng)目失敗時(shí)瞭吃,就無法直接使用數(shù)據(jù)庫的事務(wù)。

那么如果當(dāng)一個(gè)事務(wù)要跨越多個(gè)分布式服務(wù)的時(shí)候碾篡,我們應(yīng)該如何保證事務(wù)呢?

為了保證該事務(wù)可以滿足ACID虱而,一般采用2PC或者3PC。 2PC(Two Phase Commitment Protocol)开泽,實(shí)現(xiàn)分布式事務(wù)的經(jīng)典代表就是兩階段提交協(xié)議牡拇。2PC包括準(zhǔn)備階段和提交階段。在此協(xié)議中穆律,一個(gè)或多個(gè)資源管理器的活動均由一個(gè)稱為事務(wù)協(xié)調(diào)器的單獨(dú)軟件組件來控制惠呼。

我們?yōu)镈evOps服務(wù)分配一個(gè)事務(wù)管理器。那么上面的過程可以整理為如下兩個(gè)階段:

準(zhǔn)備階段:

image

提交/回滾階段:

image

2PC 提供了一套完整的分布式事務(wù)的解決方案峦耘,遵循事務(wù)嚴(yán)格的 ACID 特性剔蹋。

但是,當(dāng)在準(zhǔn)備階段的時(shí)候辅髓,對應(yīng)的業(yè)務(wù)數(shù)據(jù)會被鎖定泣崩,直到整個(gè)過程結(jié)束才會釋放鎖。如果在高并發(fā)和涉及業(yè)務(wù)模塊較多的情況下洛口,會對數(shù)據(jù)庫的性能影響較大矫付。而且隨著規(guī)模的增大,系統(tǒng)的可伸縮性越差第焰。同時(shí)由于 2PC引入了事務(wù)管理器买优,如果事務(wù)管理器和執(zhí)行的服務(wù)同時(shí)宕機(jī),則會導(dǎo)致數(shù)據(jù)產(chǎn)生不一致。雖然又提出了3PC 將2PC中的準(zhǔn)備階段再次一分為二的來解決這一問題杀赢,但是同樣可能會產(chǎn)生數(shù)據(jù)不一致的結(jié)果烘跺。

微服務(wù)架構(gòu)中應(yīng)滿足數(shù)據(jù)最終一致性原則

不可否認(rèn),2PC 和3PC 提供了解決分布式系統(tǒng)下事務(wù)一致性問題的思路脂崔,但是2PC同時(shí)又是一個(gè)非常耗時(shí)的復(fù)雜過程滤淳,會嚴(yán)重影響系統(tǒng)效率,在實(shí)踐中我們盡量避免使用它砌左。所以在分布式系統(tǒng)下無法直接使用此方案來保證事務(wù)娇钱。

對于分布式的微服務(wù)架構(gòu)而言,傳統(tǒng)數(shù)據(jù)庫的ACID原則可能并不適用绊困。首先微服務(wù)架構(gòu)自身的所有數(shù)據(jù)都是通 過API 進(jìn)行訪問。這種數(shù)據(jù)訪問方式使得微服務(wù)之間松耦合适刀,并且彼此之間獨(dú)立非常容易進(jìn)行性能擴(kuò)展秤朗。其次 不同服務(wù)通常使用不同的數(shù)據(jù)庫,甚至并不一定會使用同一類數(shù)據(jù)庫笔喉,反而使用非關(guān)系型數(shù)據(jù)庫取视,而大部分的 非關(guān)系型數(shù)據(jù)庫都不支持2PC。

在這種情況下常挚,又如何解決事務(wù)一致性問題呢作谭?

一個(gè)最直接的辦法就是考慮數(shù)據(jù)的強(qiáng)一致性。根據(jù)Eric Brewer提出的CAP理論奄毡,只能在數(shù)據(jù)強(qiáng)一致性(C)和可用性(A)之間做平衡折欠。

CAP 是指在一個(gè)分布式系統(tǒng)下,包含三個(gè)要素:Consistency(一致性)吼过、Availability(可用性)锐秦、Partition tolerance(分區(qū)容錯(cuò)性),并且三者不可得兼盗忱。

  • 一致性(Consistency)酱床,是指對于每一次讀操作,要么都能夠讀到最新寫入的數(shù)據(jù)趟佃,要么錯(cuò)誤扇谣,所有數(shù)據(jù)變動都是同步的。
  • 可用性(Availability)闲昭,是指對于每一次請求罐寨,都能夠得到一個(gè)及時(shí)的、非錯(cuò)的響應(yīng)汤纸,但是不保證請求的結(jié)果是基于最新寫入的數(shù)據(jù)衩茸。即在可以接受的時(shí)間范圍內(nèi)正確地響應(yīng)用戶請求。
  • 分區(qū)容錯(cuò)性(Partition tolerance),是指由于節(jié)點(diǎn)之間的網(wǎng)絡(luò)問題楞慈,即使一些消息丟包或者延遲幔烛,整個(gè)系統(tǒng)仍能夠提供滿足一致性和可用性的服務(wù)。

關(guān)系型數(shù)據(jù)庫單節(jié)點(diǎn)保證了數(shù)據(jù)強(qiáng)一致性(C)和可用性(A)囊蓝,但是卻無法保證分區(qū)容錯(cuò)性(P)饿悬。

然而在分布式系統(tǒng)下,為了保證模塊的分區(qū)容錯(cuò)性(P)聚霜,只能在數(shù)據(jù)強(qiáng)一致性(C)和可用性(A)之間做平衡狡恬。具體表現(xiàn)為在一定時(shí)間內(nèi),可能模塊之間數(shù)據(jù)是不一致的蝎宇,但是通過自動或手動補(bǔ)償后能夠達(dá)到最終的一致弟劲。

可用性一般是更好的選擇,但是在服務(wù)和數(shù)據(jù)庫之間維護(hù)事務(wù)一致性是非常根本的需求姥芥,微服務(wù)架構(gòu)中應(yīng)該選擇滿足最終一致性兔乞。

那么我們應(yīng)該如何實(shí)現(xiàn)數(shù)據(jù)的最終一致性呢?

使用Event Sourcing保證微服務(wù)的最終一致性

什么是Event Sourcing(事件溯源)凉唐?

一個(gè)對象從創(chuàng)建開始到消亡會經(jīng)歷很多事件庸追,傳統(tǒng)的方式是保存這個(gè)業(yè)務(wù)對象當(dāng)前的狀態(tài)。但更多的時(shí)候台囱,我們也許更關(guān)心這個(gè)業(yè)務(wù)對象是怎樣達(dá)到這一狀態(tài)的淡溯。Event Sourcing從根本上和傳統(tǒng)的數(shù)據(jù)存儲不同,它存儲的不是業(yè)務(wù)對象的狀態(tài)簿训,而是有關(guān)該業(yè)務(wù)對象一系列的狀態(tài)變化的事件咱娶。只要一個(gè)對象的狀態(tài)發(fā)生變化,服務(wù)就需要自動發(fā)布事件來附加到事件的序列中煎楣。這個(gè)操作本質(zhì)上是原子的豺总。

現(xiàn)在將上面的訂單過程用Event Sourcing 進(jìn)行改造,將訂單變動的一個(gè)個(gè)事件存儲起來择懂,服務(wù)監(jiān)聽事件喻喳,對訂單的狀態(tài)進(jìn)行修改。

http://choerodon.io/zh/blog/event-consistent/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末困曙,一起剝皮案震驚了整個(gè)濱河市表伦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌慷丽,老刑警劉巖蹦哼,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異要糊,居然都是意外死亡纲熏,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來局劲,“玉大人勺拣,你說我怎么就攤上這事∮闾睿” “怎么了药有?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長苹丸。 經(jīng)常有香客問我愤惰,道長,這世上最難降的妖魔是什么赘理? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任宦言,我火速辦了婚禮,結(jié)果婚禮上商模,老公的妹妹穿的比我還像新娘蜡励。我一直安慰自己,他們只是感情好阻桅,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著兼都,像睡著了一般嫂沉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上扮碧,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天趟章,我揣著相機(jī)與錄音,去河邊找鬼慎王。 笑死蚓土,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的赖淤。 我是一名探鬼主播蜀漆,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼咱旱!你這毒婦竟也來了确丢?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤吐限,失蹤者是張志新(化名)和其女友劉穎鲜侥,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體诸典,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡描函,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舀寓。...
    茶點(diǎn)故事閱讀 38,100評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡胆数,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出基公,到底是詐尸還是另有隱情幅慌,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布轰豆,位于F島的核電站胰伍,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏酸休。R本人自食惡果不足惜骂租,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望斑司。 院中可真熱鬧渗饮,春花似錦、人聲如沸宿刮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽僵缺。三九已至胡桃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間磕潮,已是汗流浹背翠胰。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留自脯,地道東北人之景。 一個(gè)月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像膏潮,于是被迫代替她去往敵國和親锻狗。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容