架構

中国体育彩票河北十一选五:本地讀寫的多活數據存儲架構設計要義

廣告
廣告

微信掃一掃,分享到朋友圈

本地讀寫的多活數據存儲架構設計要義
0 0

本文由公眾號EAWorld翻譯發表,轉載需注明出處。

作者:Parashar Borkotoky 

譯者:白小白 

原文://t.cn/AiKO0q4P

原題:Design Considerations in a read local write local multi-master data store

本地讀寫多活示例

本地讀-本地寫的多活數據存儲架構是最難實現的數據模式之一。這一模式也常被稱為“雙活”或者“多主”,對于不同行業大容量低延遲的事務類應用而言,這是一種必備的能力。

系統的整體可用性取決于單獨組件的可用性。用戶界面層、服務層和消息層可以跨分區/跨地域進行橫向擴展以提供高可用性,但對于事務性數據存儲(尤其是寫操作)而言,采用同樣的處理方案仍舊充滿挑戰。無論部署在本地或者云端,很多關系型數據庫和noSQL數據庫都提供了這種開箱即用的能力。也有一些企業選擇自己實現定制化的復制方案來達成多活的目標,對于強烈依賴低延遲的用戶尤其如此。忽略方案的差異性,人們需要對一些通用的風險與權衡進行仔細考量。同步復制與異步復制

首當其沖需要考慮的就是在跨可用域的數據復制過程中,是采用同步復制還是異步復制的方案。

同步復制技術需要實現多可用域/可用區間的同步寫入。這將會帶來很多的問題:

  1. 隨著可用域的增加,寫入延遲也將逐漸增加
  2. 域內的服務需要同步的訪問域外資源,這通?;崍鈑虻幕厥蘸妥票淶酶癰叢?/li>
  3. 故障檢測和恢復會變得越來越復雜。本地域的數據存儲寫入成功,對其他域的數據存儲寫入失敗,這種情況該怎么處理?其他域的數據存儲的不可用,是否應該影響本地域的服務可用性?

鑒于以上的這些因素,異步復制通常是首選方案,從而也引入了最終一致性的話題。擁抱最終一致性

CAP定理

CAP定理指出,對于一個分布式的數據庫系統而言,一致性(C)、可用性(A)和分區容忍性(P)三者僅能居其二。因為分區容忍性是現代分布式系統的必備要件,這將歸結為在一致性和可用性之間取得一個平衡。PACELC定理進一步擴展了CAP的理念,并指出,即使不考慮分區的情況,仍舊需要在延遲(L)和一致性(C)之間進行一定的權衡。

譯注:PACELC中的E即Else,也就是或者。對于有分區的情況,需要權衡AC,或者,在沒分區的情況,需要權衡LC

在大量的用例中,最終一致性是可接受的妥協。比如審計或者遵從性日志、產品目錄或者搜索索引,對于此類的應用而言,數據存儲的最終一致性是完全可接受的。但對于其他一些場景,比如銀行事務、航班預訂或者股票市場而言,即使是毫秒級的不一致性,也將損害用戶體驗或者系統可信性。

在這樣的情況下,值得評估一下多活的數據存儲方案是否符合用戶場景的需要。

  1. 本地讀取-全局寫入的方式提供了可用性和一致性之間的平衡,是一種可選的方案。在對某個可用域的主副本數據存儲進行寫入操作的同時,會在其他可用域生成只讀副本。當主副本數據發生單點失敗問題的時候,可以在其他可用域中選擇一個新的主副本,從而實現快速的故障恢復,這種方式所提供的可用性,對于很多場景來說是可接受的。
  2. 另一種方式是分片寫入或者分區寫入,這將使得可用域中某一份單獨的數據存儲成為一部分數據的主副本。

一旦決定采用多活的數據存儲方案,并且接納了最終一致性的理念,接下來需要重點考慮的就是采用合適的技術,以緩解和減輕一致性問題所產生的影響。采用事件流進行復制

在多活架構下,數據的異步復制通常采用事件流的方式實現。好處如下:

  1. 寫入操作的順序將得以保留。這對很多用戶場景來說是必須的。
  2. 對于寫入失敗或者存儲不可用的情況,事件復制器將持續的嘗試對副本數據的寫入操作直到成功,以保證故障可以被恢復。

這一方案的挑戰在于,如何讓事件復制器處于高可用的狀態。這需要在順序復制和并行復制之間做出設計上的權衡。寫入前的業務驗證

在數據復制的過程中,復制器沒有辦法知道寫入的發起者是誰,但寫入本身可能存在不一致性或者錯誤的參數。為了避免寫入的過程對業務邏輯造成不可挽回的錯誤(尤其是在事件的順序至關重要的場合),復制過程將被阻塞,直到當前的事件已經成功處理,才會繼續進行下一項操作。

因此,在寫入前進行足夠的業務驗證是十分必要的,這將避免情況變得難以收拾。一些與網絡或者與系統的不可用有關的問題,都是可恢復的,復制器可以用重試的方式對此類情況進行處理。更新操作帶來的問題

考慮如下的業務場景:顧客在建立訂單后進行了更新或者取消操作。

  • 步驟1:生成訂單 
  • 步驟2:更新訂單

在這種情況下,對于第2步操作來說,應用通常需要獲取訂單的信息(讀),并且更新訂單的狀態(寫)。這是所有訂單系統的通用場景,如訂票、生產制造、貿易或者零售。

在最終一致性的架構下,如果步驟1和步驟2分屬于不同的可用域,這通?;嵋⒁恍┪侍?。比如,當步驟1沒能及時的復制到步驟2所在的可用域的時候,步驟2的更新操作就可能失敗。

更新操作帶來的問題示意

以上的場景帶來的不只是用戶體驗的不理想,更重要的是分引發數據不一致的問題:一種情況是,步驟2的更新的操作可能基于一份過時的數據,甚至步驟1的復制操作覆蓋了步驟2的更新操作。事件與狀態

在上面的例子中,考慮了兩個事件:訂單生成和訂單更新。假定接下來又發生了兩個事件:訂單更新和訂單取消。

大多數的數據存儲方案會將所有這些事件存儲在一個歷史實體、審計實體或者細節實體中,用以表征單獨的事件。我們稱之為“事件實體”。

在很多情況下,訂單的當前狀態也會被記錄,如“已取消”。我們稱之為“狀態實體”。

對于每一個新的事件而言,有兩個必不可少的操作,對事件實體的插入操作,和對狀態實體的更新操作。

訂單事件示意

沒有狀態實體,我們就需要去匯總所有的事件或者獲取最新的事件來獲知訂單的狀態。

在有些情況下,數據存儲僅支持插入而不支持更新。這樣就只有事件實體而沒有狀態實體。這是否有助于補救更新操作所產生的問題呢?完全不會。尤其是在上文提到的讀取過時數據的情形下。當然,當復制器之間或者服務寫入之間發生沖突的時候,這確實有助于確保數據不會被覆蓋。

在此情形下,寫入操作的“只插”策略,或者事件溯源的設計方法將很實用。粘滯會話

在上文所提到的更新問題中,插入、讀取和更新操作分屬于不同的可用域,但卻共享一個相同的上下文(如訂單ID),只有在這種情況才會發生問題。雖然在理想情況下,服務請求應該是無狀態的,但如果與某一個上下文(如用戶或者訂單)有關的狀態可以用Session、Cookie或規則的方式保存在流量管理器中,就可以確保在多數情況下,與某一個特定的上下文有關的一組事件可以被路由到一個共同的可用域。這種程度的會話粘滯或者會話親和性可以極大的改善數據過時的問題。沖突解決方案

作為預防性措施,業務驗證、會話粘滯或者事件溯源可以在很大程度上緩解相關的風險,讓本地讀寫多活方案的實現更加健壯。然而,沖突是不可避免的。對于一些場景,尤其是高頻的副本復制的場景下,需要認真考慮沖突的解決方案。

一些沖突解決方案包括:

  1. 基于時間戳的解決方案:比如,以最新寫入的為準
  2. 基于規則的解決方案:比如,在進行副本復制的過程中,如果符合某種特定條件,則忽略事件的寫入。

雖然多數沖突解決方案可以自動執行,對于一些特定的場景,我們仍舊需要建立一個可視化的用戶界面來手動的解決沖突問題。結語

跨可用域的本地讀寫的多活實現是一項復雜的的任務,通常需要在應用的數據層以外解決很多問題。這是一種很難實現和治理的模型,僅在低延遲和高可用性不可或缺的場景下才需要考慮。仔細的分析和規劃相關的設計考量、妥協和治理要素,將有助于達成最優的解決方案。同時,也需要考慮采用節流方法來理解延遲和可用性之間的平衡。

譯注:節流方法(throttled approach):類似機場或者地鐵的安檢方式,當流量較大的時候,一部分人會被滯留在一個等待區內,直到前面的一批已經安全順利通過。

關于EAWorld:微服務,DevOps,數據治理,移動架構原創技術分享

我還沒有學會寫個人說明!

從 GFS 失敗的架構設計來看一致性的重要性

上一篇

技術總監到底要不要寫代碼?

下一篇

你也可能喜歡

本地讀寫的多活數據存儲架構設計要義

長按儲存圖像,分享給朋友

ITPUB 每周精要將以郵件的形式發放至您的郵箱


微信掃一掃

微信掃一掃