互聯網行業是大勢所趨,從招聘工資水平便可看出,那麼如何提高自我技能,知足互聯網行業技能要求?須要以目標爲導向,進行技能提高,本文主要針對高併發分佈式系統設計、架構(數據一致性)作了分析,祝各位早日走上屬於本身的"成金之路"。
目錄:
問題分析
概念解讀
Most Simple原理解讀
eBey、去哪兒、蘑菇街分佈式事務案例分析
參考資料
1.問題解析
要想作架構,必須識別出問題,便是誰的問題,什麼問題。
明顯的,分佈式架構解決的是高併發的問題,高併發下服務高可用和數據一致性問題問題;當規模規模較小時,單庫HA便可知足請求,當業務規模持續增長,單庫已經沒法知足業務需求,業界主流作法,是對業務進行分表、分庫,那麼原來的有些業務,如今則要在一個事務中,保證兩個庫同時操做成功或操做不成功(一個庫成功,一個庫失敗,要麼從新嘗試失敗庫操做直到成功,要麼回滾成功庫)。隨之而來的問題既是如何保證分庫時業務操做的數據一致性。理解高併發分佈式架構、分佈式系統數據一致性的問題、起源是第一步。
這裏多囉嗦一點,分庫後,每一個庫能夠採起不一樣的語言,以時下很流行的微服務向外提供服務;可是業務量不大的狀況下,使用微服務到增長了複雜性及技術成本。明白技術的起源,針對不一樣的業務量,採起適當的架構、以最恰當的方式承載業務,是架構師必須具有的能力。
2.常見概念解讀:
a.關係型數據庫一般具備ACID特性:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)。
b.Base(basically available, soft state, eventually consistent):一種 Acid 的替代方案,BASE 的可用性是經過支持局部故障而不是系統全局故障來實現的。化學理論中ACID是酸、Base剛好是鹼。
c.CAP定律:在分佈式系統中,同時知足"CAP定律"中的"一致性"、"可用性"和"分區容錯性"三者是不可能的。
d.強一致:當更新操做完成以後,任何多個後續進程或者線程的訪問都會返回最新的更新過的值。這種是對用戶最友好的,就是用戶上一次寫什麼,下一次就保證能讀到什麼。根據 CAP 理論,這種實現須要犧牲可用性,常見的RDBMS。
e.弱一致性:系統並不保證續進程或者線程的訪問都會返回最新的更新過的值。系統在數據寫入成功以後,不承諾當即能夠讀到最新寫入的值,也不會具體的承諾多久以後能夠讀到。
f.最終一致性:弱一致性的特定形式。系統保證在沒有後續更新的前提下,系統最終返回上一次更新操做的值。在沒有故障發生的前提下,不一致窗口的時間主要受通訊延遲,系統負載和複製副本的個數影響。DNS 是一個典型的最終一致性系統。
爲保證可用性,互聯網分佈式架構將
強一致性需求轉換成
最終一致性的需求,並經過系統執行
冪等性的保證,保證數據的最終一致性。
※冪等性(Idempotence):分佈式架構的基石,即同一個操做不管請求多少次,其結果都相同。
典型的是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.
每一個概念實際所解決的是人遇到的某個特定的問題,發現其背後所表明的問題,是理解高併發分佈式架構、分佈式系統數據一致性第二步。
3.Most Simple原理解讀
假設有一個從帳戶取錢的遠程API(能夠是HTTP的,也能夠不是),咱們暫時用類函數的方式記爲:
bool withdraw(account_id, amount)
withdraw的語義是從account_id對應的帳戶中扣除amount數額的錢;若是扣除成功則返回true,帳戶餘額減小amount;若是扣除失敗則返回false,帳戶餘額不變。
值得注意的是:和本地環境相比,咱們不能輕易假設
環境的可靠性。
一種典型的場景是withdraw請求已經被服務器端正確處理,但服務器端的返回結果因爲網絡等緣由被掉丟了,致使客戶端沒法得知處理結果。若是是在網頁上,一些不恰當的設計可能會使用戶認爲上一次操做失敗了,而後刷新頁面,這就致使了withdraw被調用兩次,帳戶也被多扣了一次錢。如圖1所示:
一種更輕量級的解決方案是冪等設計。咱們能夠經過一些技巧把withdraw變成冪等的,好比:
int create_ticket()
bool idempotent_withdraw(ticket_id, account_id, amount)
create_ticket的語義是獲取一個服務器端生成的惟一的處理號ticket_id,它將用於標識後續的操做。idempotent_withdraw和withdraw的區別在於關聯了一個ticket_id,一個ticket_id表示的操做至多隻會被處理一次,每次調用都將返回第一次調用時的處理結果。這樣,idempotent_withdraw就符合冪等性了,客戶端就能夠放心地屢次調用。
基於冪等性的解決方案中一個完整的取錢流程被分解成了兩個步驟:1.調用create_ticket()獲取ticket_id;2.調用idempotent_withdraw(ticket_id, account_id, amount)。雖然create_ticket不是冪等的,但在這種設計下,它對系統狀態的影響能夠忽略,加上idempotent_withdraw是冪等的,因此任何一步因爲網絡等緣由失敗或超時,客戶端均可以重試,直到得到結果。如圖所示:
和分佈式事務相比,冪等設計的優點在於它的輕量級,容易適應異構環境,以及性能和可用性方面。在某些性能要求比較高的應用,冪等設計每每是惟一的選擇。
冪等性是高併發分佈式架構、分佈式系統數據一致性的底層基本原理,理解這一步,是走上"成金之路"的關鍵。
4.案例分析
a.eBay經典的BASE模式
一個最多見的場景,若是產生了一筆交易,須要在交易表增長記錄,同時還要修改用戶表的金額。這兩個表屬於不一樣的庫及遠程服務,因此就涉及到分佈式事務一致性的問題。
核心思想是用兩個事務來保證一致性,同時用異步保證了可用性:一個事務處理主要操做"增長交易表記錄"與異步消息構建,另一個事務用來處理構建的異步消息;第一個事務即處理主要業務又記錄次要業務,同時還能快速返回,保證了高可用性,第二個事務則用來保證數據的一致性。(即將buyer和seller表更新的處理轉爲"線下"處理,消息日誌能夠存儲到本地文本、數據庫或消息隊列,再經過業務規則自動或人工發起重試。人工重試更多的是應用於支付場景,經過對帳系統對過後問題的處理,相似與淘寶雙11重複支付後續退款)
一個經典的解決方法,將主要修改操做以及更新用戶表的"異步消息"放在一個本地事務來完成。同時爲了達到屢次重試的冪等性,避免重複消費用戶表消息帶來的問題,增長一個更新記錄表
updates_applied 來記錄已經處理過的消息。
在第一事務中,經過本地的數據庫的事務保障,保證"增長交易表記錄"、"增長兩條異步消息隊列記錄(一條處理buyer表、一條處理seller表)",同時成功或同時失敗。
在第二事務中,分別讀出消息隊列(但不刪除),經過判斷更新記錄表 updates_applied 來檢測相關消息是否被執行,如沒執行,則執行相關業務邏輯(保證冪等性,保證即便執行過程當中異常,重複執行沒有任何問題),執行完全部消息後而後增長一條操做記錄到updates_applied,事務到此結束。用事務保證兩個異步消息執行及updates_applied的一致性操做(又稱爲分佈式事務框架)。最後刪除隊列。
b.去哪兒網分佈式事務方案
i.優先使用異步方案,原理和"a.eBay經典的BASE模式"相似,對業務邏輯處理不能保證"冪等性"的,增長去重表(即a中的updates_applied) 來處理
ii.對於不適合異步消息處理的業務,如A、B、C三方須要同步處理才能返回:在A、B、C三個庫中分別維護一個事務記錄表recorda/recordb/recordc,當A、B、C業務事務處理完,將結果存到對應的recordx中,由一箇中心服務對比查詢三方的事物記錄表,有以下兩種處理方式:
第一種:A、B成功,C失敗了,重試C,知道C成功;
第二種:C不可能成功時,回滾A、B,如C爲扣庫存,當庫存爲0時,則不能成功(不考慮補庫存)。
另,這種recordx表由RPC框架層進行維護,對業務是透明的。
c.蘑菇街交易建立過程
場景:將下單功能拆分爲12個子業務(見參考資料b),對於非實時、非強一致性的關聯業務,使用"eBay經典的BASE模式"思想,第一個本地事務執行成功後,以發消息通知、關聯事務異步化執行方案,來避免a中第二個事務的"分佈式事務框架"對業務帶來的侵入和複雜性,具體方案是基於DB事件變化通知給MQ,而MQ消費者經過ACK,保證消息必定消費成功,完成強一致性(消息可能會被重發,因此消息消費方要保證冪等性)。
而對要求同步作、強一致性要求的場景(和b的ii相同場景),如優惠券和優惠券減庫存:能夠引入"a.eBay經典的BASE模式"的第二個事務(分佈式事務框架)來處理,可是複雜性會急劇上升;
另外一種方式是建立一個不可見訂單,而後在同步調用鎖券和扣減庫存時,針對調用異常(失敗或者超時),發出廢單消息到MQ。若是消息發送失敗,本地會作時間階梯式的異步重試;優惠券系統和庫存系統收到消息後,會進行判斷是否須要作業務回滾,這樣就準實時地保證了多個本地事務的最終一致性。
根據業務進行不一樣的方案處理,解決了高併發分佈式架構、分佈式系統的數據一致性問題。
總體來講,蘑菇街的案例可遷移性強,可移植性好,能夠嘗試模擬下實際場景,駕馭分佈式架構、分佈式系統數據一致性方案,祝你們早日走上"成金之路",看到這裏,煩請不吝"推薦",謝謝!
5.參考資料: