強(qiáng)勢解析eBay BASE模式、去哪兒及蘑菇街分布式架構(gòu)
互聯(lián)網(wǎng)行業(yè)是大勢所趨,從招聘工資水平即可看出,那么如何提升自我技能,滿足互聯(lián)網(wǎng)行業(yè)技能要求?需要以目標(biāo)為導(dǎo)向,進(jìn)行技能提升,本文主要針對高并發(fā)分布式系統(tǒng)設(shè)計(jì)、架構(gòu)(數(shù)據(jù)一致性)做了分析,祝各位早日走上屬于自己的”成金之路”。
目錄:
- 問題分析
- 概念解讀
- Most Simple原理解讀
- eBey、去哪兒、蘑菇街分布式事務(wù)案例分析
- 參考資料
1.問題解析
要想做架構(gòu),必須識(shí)別出問題,即是誰的問題,什么問題。
明顯的,分布式架構(gòu)解決的是高并發(fā)的問題,高并發(fā)下服務(wù)高可用和數(shù)據(jù)一致性問題問題;當(dāng)規(guī)模規(guī)模較小時(shí),單庫HA即可滿足請求,當(dāng)業(yè)務(wù)規(guī)模持續(xù)增加,單庫已經(jīng)無法滿足業(yè)務(wù)需求,業(yè)界主流做法,是對業(yè)務(wù)進(jìn)行分表、分庫,那么原來的有些業(yè)務(wù),現(xiàn)在則要在一個(gè)事務(wù)中,保證兩個(gè)庫同時(shí)操作成功或操作不成功(一個(gè)庫成功,一個(gè)庫失敗,要么重新嘗試失敗庫操作直到成功,要么回滾成功庫)。隨之而來的問題既是如何保證分庫時(shí)業(yè)務(wù)操作的數(shù)據(jù)一致性。理解高并發(fā)分布式架構(gòu)、分布式系統(tǒng)數(shù)據(jù)一致性的問題、起源是***步。
這里多啰嗦一點(diǎn),分庫后,每個(gè)庫可以采取不同的語言,以時(shí)下很流行的微服務(wù)向外提供服務(wù);但是業(yè)務(wù)量不大的情況下,使用微服務(wù)到增加了復(fù)雜性及技術(shù)成本。明白技術(shù)的起源,針對不同的業(yè)務(wù)量,采取適當(dāng)?shù)募軜?gòu)、以最恰當(dāng)?shù)姆绞匠休d業(yè)務(wù),是架構(gòu)師必須具備的能力。
2.常見概念解讀:
a.關(guān)系型數(shù)據(jù)庫通常具有ACID特性:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)。
b.Base(basically available, soft state, eventually consistent):一種 Acid 的替代方案,BASE 的可用性是通過支持局部故障而不是系統(tǒng)全局故障來實(shí)現(xiàn)的?;瘜W(xué)理論中ACID是酸、Base恰好是堿。
c.CAP定律:在分布式系統(tǒng)中,同時(shí)滿足”CAP定律”中的”一致性”、”可用性”和”分區(qū)容錯(cuò)性”三者是不可能的。
d.強(qiáng)一致:當(dāng)更新操作完成之后,任何多個(gè)后續(xù)進(jìn)程或者線程的訪問都會(huì)返回***的更新過的值。這種是對用戶最友好的,就是用戶上一次寫什么,下一次就保證能讀到什么。根據(jù) CAP 理論,這種實(shí)現(xiàn)需要犧牲可用性,常見的RDBMS。
e.弱一致性:系統(tǒng)并不保證續(xù)進(jìn)程或者線程的訪問都會(huì)返回***的更新過的值。系統(tǒng)在數(shù)據(jù)寫入成功之后,不承諾立即可以讀到***寫入的值,也不會(huì)具體的承諾多久之后可以讀到。
f.最終一致性:弱一致性的特定形式。系統(tǒng)保證在沒有后續(xù)更新的前提下,系統(tǒng)最終返回上一次更新操作的值。在沒有故障發(fā)生的前提下,不一致窗口的時(shí)間主要受通信延遲,系統(tǒng)負(fù)載和復(fù)制副本的個(gè)數(shù)影響。DNS 是一個(gè)典型的最終一致性系統(tǒng)。
為保證可用性,互聯(lián)網(wǎng)分布式架構(gòu)將強(qiáng)一致性需求轉(zhuǎn)換成最終一致性的需求,并通過系統(tǒng)執(zhí)行冪等性的保證,保證數(shù)據(jù)的最終一致性。
※冪等性(Idempotence):分布式架構(gòu)的基石,即同一個(gè)操作無論請求多少次,其結(jié)果都相同。
典型的是HTTP,Methods can also have the property of “idempotence” in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.
每個(gè)概念實(shí)際所解決的是人遇到的某個(gè)特定的問題,發(fā)現(xiàn)其背后所代表的問題,是理解高并發(fā)分布式架構(gòu)、分布式系統(tǒng)數(shù)據(jù)一致性第二步。
3.Most Simple原理解讀
假設(shè)有一個(gè)從賬戶取錢的遠(yuǎn)程API(可以是HTTP的,也可以不是),我們暫時(shí)用類函數(shù)的方式記為:
bool withdraw(account_id, amount)
withdraw的語義是從account_id對應(yīng)的賬戶中扣除amount數(shù)額的錢;如果扣除成功則返回true,賬戶余額減少amount;如果扣除失敗則返回false,賬戶余額不變。
值得注意的是:和本地環(huán)境相比,我們不能輕易假設(shè)環(huán)境的可靠性。
一種典型的場景是withdraw請求已經(jīng)被服務(wù)器端正確處理,但服務(wù)器端的返回結(jié)果由于網(wǎng)絡(luò)等原因被掉丟了,導(dǎo)致客戶端無法得知處理結(jié)果。如果是在網(wǎng)頁上,一些不恰當(dāng)?shù)脑O(shè)計(jì)可能會(huì)使用戶認(rèn)為上一次操作失敗了,然后刷新頁面,這就導(dǎo)致了withdraw被調(diào)用兩次,賬戶也被多扣了一次錢。如圖1所示:
一種更輕量級(jí)的解決方案是冪等設(shè)計(jì)。我們可以通過一些技巧把withdraw變成冪等的,比如:
int create_ticket()
bool idempotent_withdraw(ticket_id, account_id, amount)
create_ticket的語義是獲取一個(gè)服務(wù)器端生成的唯一的處理號(hào)ticket_id,它將用于標(biāo)識(shí)后續(xù)的操作。idempotent_withdraw和withdraw的區(qū)別在于關(guān)聯(lián)了一個(gè)ticket_id,一個(gè)ticket_id表示的操作至多只會(huì)被處理一次,每次調(diào)用都將返回***次調(diào)用時(shí)的處理結(jié)果。這樣,idempotent_withdraw就符合冪等性了,客戶端就可以放心地多次調(diào)用。
基于冪等性的解決方案中一個(gè)完整的取錢流程被分解成了兩個(gè)步驟:1.調(diào)用create_ticket()獲取ticket_id;2.調(diào)用idempotent_withdraw(ticket_id, account_id, amount)。雖然create_ticket不是冪等的,但在這種設(shè)計(jì)下,它對系統(tǒng)狀態(tài)的影響可以忽略,加上idempotent_withdraw是冪等的,所以任何一步由于網(wǎng)絡(luò)等原因失敗或超時(shí),客戶端都可以重試,直到獲得結(jié)果。如圖所示:
和分布式事務(wù)相比,冪等設(shè)計(jì)的優(yōu)勢在于它的輕量級(jí),容易適應(yīng)異構(gòu)環(huán)境,以及性能和可用性方面。在某些性能要求比較高的應(yīng)用,冪等設(shè)計(jì)往往是唯一的選擇。
冪等性是高并發(fā)分布式架構(gòu)、分布式系統(tǒng)數(shù)據(jù)一致性的底層基本原理,理解這一步,是走上”成金之路”的關(guān)鍵。
4.案例分析
a.eBay經(jīng)典的BASE模式
一個(gè)最常見的場景,如果產(chǎn)生了一筆交易,需要在交易表增加記錄,同時(shí)還要修改用戶表的金額。這兩個(gè)表屬于不同的庫及遠(yuǎn)程服務(wù),所以就涉及到分布式事務(wù)一致性的問題。
核心思想是用兩個(gè)事務(wù)來保證一致性,同時(shí)用異步保證了可用性:一個(gè)事務(wù)處理主要操作”增加交易表記錄”與異步消息構(gòu)建,另外一個(gè)事務(wù)用來處理構(gòu)建的異步消息;***個(gè)事務(wù)即處理主要業(yè)務(wù)又記錄次要業(yè)務(wù),同時(shí)還能快速返回,保證了高可用性,第二個(gè)事務(wù)則用來保證數(shù)據(jù)的一致性。(即將buyer和seller表更新的處理轉(zhuǎn)為”線下”處理,消息日志可以存儲(chǔ)到本地文本、數(shù)據(jù)庫或消息隊(duì)列,再通過業(yè)務(wù)規(guī)則自動(dòng)或人工發(fā)起重試。人工重試更多的是應(yīng)用于支付場景,通過對賬系統(tǒng)對事后問題的處理,類似與淘寶雙11重復(fù)支付后續(xù)退款)
一個(gè)經(jīng)典的解決方法,將主要修改操作以及更新用戶表的”異步消息”放在一個(gè)本地事務(wù)來完成。同時(shí)為了達(dá)到多次重試的冪等性,避免重復(fù)消費(fèi)用戶表消息帶來的問題,增加一個(gè)更新記錄表 updates_applied 來記錄已經(jīng)處理過的消息。
在***事務(wù)中,通過本地的數(shù)據(jù)庫的事務(wù)保障,保證”增加交易表記錄”、”增加兩條異步消息隊(duì)列記錄(一條處理buyer表、一條處理seller表)”,同時(shí)成功或同時(shí)失敗。
在第二事務(wù)中,分別讀出消息隊(duì)列(但不刪除),通過判斷更新記錄表 updates_applied 來檢測相關(guān)消息是否被執(zhí)行,如沒執(zhí)行,則執(zhí)行相關(guān)業(yè)務(wù)邏輯(保證冪等性,保證即使執(zhí)行過程中異常,重復(fù)執(zhí)行沒有任何問題),執(zhí)行完所有消息后然后增加一條操作記錄到updates_applied,事務(wù)到此結(jié)束。用事務(wù)保證兩個(gè)異步消息執(zhí)行及updates_applied的一致性操作(又稱為分布式事務(wù)框架)。***刪除隊(duì)列。
b.去哪兒網(wǎng)分布式事務(wù)方案
i.優(yōu)先使用異步方案,原理和”a.eBay經(jīng)典的BASE模式”類似,對業(yè)務(wù)邏輯處理不能保證”冪等性”的,增加去重表(即a中的updates_applied) 來處理
ii.對于不適合異步消息處理的業(yè)務(wù),如A、B、C三方需要同步處理才能返回:在A、B、C三個(gè)庫中分別維護(hù)一個(gè)事務(wù)記錄表recorda/recordb/recordc,當(dāng)A、B、C業(yè)務(wù)事務(wù)處理完,將結(jié)果存到對應(yīng)的recordx中,由一個(gè)中心服務(wù)對比查詢?nèi)降氖挛镉涗洷?,有如下兩種處理方式:
***種:A、B成功,C失敗了,重試C,知道C成功;
第二種:C不可能成功時(shí),回滾A、B,如C為扣庫存,當(dāng)庫存為0時(shí),則不能成功(不考慮補(bǔ)庫存)。
另,這種recordx表由RPC框架層進(jìn)行維護(hù),對業(yè)務(wù)是透明的。
c.蘑菇街交易創(chuàng)建過程
場景:將下單功能拆分為12個(gè)子業(yè)務(wù)(見參考資料b),對于非實(shí)時(shí)、非強(qiáng)一致性的關(guān)聯(lián)業(yè)務(wù),使用”eBay經(jīng)典的BASE模式”思想,***個(gè)本地事務(wù)執(zhí)行成功后,以發(fā)消息通知、關(guān)聯(lián)事務(wù)異步化執(zhí)行方案,來避免a中第二個(gè)事務(wù)的”分布式事務(wù)框架”對業(yè)務(wù)帶來的侵入和復(fù)雜性,具體方案是基于DB事件變化通知給MQ,而MQ消費(fèi)者通過ACK,保證消息一定消費(fèi)成功,完成強(qiáng)一致性(消息可能會(huì)被重發(fā),所以消息消費(fèi)方要保證冪等性)。
而對要求同步做、強(qiáng)一致性要求的場景(和b的ii相同場景),如優(yōu)惠券和優(yōu)惠券減庫存:可以引入”a.eBay經(jīng)典的BASE模式”的第二個(gè)事務(wù)(分布式事務(wù)框架)來處理,但是復(fù)雜性會(huì)急劇上升;
另一種方式是創(chuàng)建一個(gè)不可見訂單,然后在同步調(diào)用鎖券和扣減庫存時(shí),針對調(diào)用異常(失敗或者超時(shí)),發(fā)出廢單消息到MQ。如果消息發(fā)送失敗,本地會(huì)做時(shí)間階梯式的異步重試;優(yōu)惠券系統(tǒng)和庫存系統(tǒng)收到消息后,會(huì)進(jìn)行判斷是否需要做業(yè)務(wù)回滾,這樣就準(zhǔn)實(shí)時(shí)地保證了多個(gè)本地事務(wù)的最終一致性。
根據(jù)業(yè)務(wù)進(jìn)行不同的方案處理,解決了高并發(fā)分布式架構(gòu)、分布式系統(tǒng)的數(shù)據(jù)一致性問題。
整體來說,蘑菇街的案例可遷移性強(qiáng),可移植性好,可以嘗試模擬下實(shí)際場景,駕馭分布式架構(gòu)、分布式系統(tǒng)數(shù)據(jù)一致性方案,祝大家早日走上”成金之路”,看到這里,煩請不吝”推薦”,謝謝!
5.參考資料:
a.冪等性http://www.cnblogs.com/weidagang2046/archive/2011/06/04/idempotence.html
b.架構(gòu)案例詳細(xì)http://weibo.com/ttarticle/p/show?id=2309403965965003062676
c.http://www.infoq.com/cn/articles/solution-of-distributed-system-transaction-consistency