深入解析NoSQL資料庫的分布式演算法

來源:互聯網
上載者:User

深入解析NoSQL資料庫的分布式演算法

系統的可擴充性是推動NoSQL運動發展的的主要理由,包含了分布式系統協調,容錯移轉,資源管理和許多其他特性。這麼講使得NoSQL聽起來像是一個大筐,什麼都能塞進去。儘管NoSQL運動並沒有給分布式資料處理帶來根本性的技術變革,但是依然引發了鋪天蓋地的關於各種協議和演算法的研究以及實踐。正是通過這些嘗試逐漸總結出了一些行之有效資料庫構建方法。在這篇文章裡,我將針對NoSQL資料庫的分布式特點進行一些系統化的描述。

接下來我們將研究一些分布式策略,比如故障檢測中的複製,這些策略用黑體字標出,被分為三段:

  • 資料一致性。NoSQL需要在分布式系統的一致性,容錯性和效能,低延遲及高可用之間作出權衡,一般來說,資料一致性是一個必選項,所以這一節主要是關於資料複製和資料恢複。
  • 資料放置。一個資料庫產品應該能夠應對不同的資料分布,叢集拓撲和硬體設定。在這一節我們將討論如何分布以及調整資料分布才能夠能夠及時解決故障,提供持久化保證,高效查詢和保證叢集中的資源(如記憶體和硬碟空間)得到均衡使用。
  • 對等系統。像 leader election 這樣的的技術已經被用於多個資料庫產品以實現容錯和資料強一致性。然而,即使是分散的的資料庫(無中心)也要跟蹤它們的全域狀態,檢測故障和拓撲變化。這一節將介紹幾種使系統保持一致狀態的技術。
資料一致性

眾所周知,分布式系統經常會遇到網路隔離或是延遲的情況,在這種情況下隔離的部分是停用,因此要保持高可用性而不犧牲一致性是不可能的。這一事實通常被稱作“CAP理論”。然而,一致性在分布式系統中是一個非常昂貴的東西,所以經常需要在這上面做一些讓步,不只是針對可用性,還有多種權衡。為了研究這些權衡,我們注意到分布式系統的一致性問題是由資料隔離和複製引起的,所以我們將從研究複製的特點開始:

  • 可用性。在網路隔離的情況下剩餘部分仍然可以應對讀寫請求。
  • 讀寫延遲。讀寫請求能夠在短時間內處理。
  • 讀寫延展性。讀寫的壓力可由多個節點均衡分擔。
  • 容錯性。對於讀寫請求的處理不依賴於任何一個特定節點。
  • 資料持久性。特定條件下的節點故障不會造成資料丟失。
  • 一致性。一致性比前面幾個特性都要複雜得多,我們需要詳細討論一下幾種不同的觀點。 但是我們不會涉及過多的一致性理論和並行存取模型,因為這已經超出了本文的範疇,我只會使用一些簡單特點構成的精簡體系。
  • 讀寫一致性。從讀寫的觀點來看,資料庫的基本目標是使副本趨同的時間儘可能短(即更新傳遞到所有副本的時間),保證最終一致性。除了這個較弱的保證,還有一些更強的一致性特點:
  • 寫後讀一致性。在資料項目X上寫操作的效果總是能夠被後續的X上的讀操作看見。
  • 讀後讀一致性。在一次對資料項目X的讀操作之後,後續對X的讀操作應該返回與第一次的傳回值相同或是更加新的值。
  • 寫一致性。分區的資料庫經常會發生寫衝突。資料庫應當能處理這種衝突並保證多個寫請求不會被不同的分區所處理。這方面資料庫提供了幾種不同的一致性模型:
  • 原子寫。假如資料庫提供了API,一次寫操作只能是一個單獨的原子性的賦值,避免寫衝突的辦法是找出每個資料的“最新版本”。這使得所有的節點都能夠在更新結束時獲得同一版本,而與更新的順序無關,網路故障和延遲經常造成各節點更新順序不一致。 資料版本可以用時間戳記或是使用者指定的值來表示。Cassandra用的就是這種方法。
  • 原子化的讀-改-寫。應用有時候需要進行 讀-改-寫 序列操作而非單獨的原子寫操作。假如有兩個用戶端讀取了同一版本的資料,修改並且把修改後的資料寫回,按照原子寫模型,時間上比較靠後的那一次更新將會覆蓋前一次。這種行為在某些情況下是不正確的(例如,兩個用戶端往同一個列表值中添加新值)。資料庫提供了至少兩種解決方案:
  • 衝突預防。 讀-改-寫 可以被認為是一種特殊情況下的事務,所以分布式鎖或是 PAXOS這樣的一致協議都可以解決這種問題。這種支援人員原子讀改寫語義和任意隔離等級的事務。另一種方法是避免分布式的並發寫操作,將對特定資料項目的所有寫操作路由到單個節點上(可以是全域主節點或者分區主節點)。為了避免衝突,資料庫必須犧牲網路隔離情況下的可用性。這種方法常用於許多提供強一致性保證的系統(例如大多數關聯式資料庫,HBase,MongoDB)。
  • 衝突檢測。資料庫跟蹤並發更新的衝突,並選擇復原其中之一或是維持兩個版本交由用戶端解決。並發更新通常用向量時鐘 (這是一種樂觀鎖)來跟蹤,或者維護一個完整的版本曆史。這個方法用於 Riak, Voldemort, CouchDB.

現在讓我們仔細看看常用的複製技術,並按照描述的特點給他們分一下類。第一幅圖描繪了不同技術之間的邏輯關係和不同技術在系統的一致性、擴充性、可用性、延遲性之間的權衡座標。 第二張圖詳細描繪了每個技術。

複本因子是4。讀寫協調者可以是一個外部客戶端或是一個內部代理節點。

《NoSQL資料庫入門》,高清PDF 版下載見

NoSQL資料庫的基礎知識

公司專屬應用程式NoSQL的關鍵

我們會依據一致性從弱到強把所有的技術過一遍:

(A, 反熵) 一致性最弱,基於策略如下。寫操作的時候選擇任意一個節點更新,在讀的時候如果新資料還沒有通過背景反熵協議傳遞到讀的那個節點,那麼讀到的仍然是舊資料。(下一節會詳細介紹反熵協議)。這種方法的主要特點是:

 
  • 過高的傳播延遲使它在資料同步方面不太好用,所以比較典型的用法是只作為輔助性的功能來檢測和修複計劃外的不一致。Cassandra就使用了反熵演算法來在各節點之間傳遞資料庫拓撲和其他一些中繼資料資訊。
  • 一致性保證較弱:即使在沒有發生故障的情況下,也會出現寫衝突與讀寫不一致。
  • 在網路隔離下的高可用和健壯性。用非同步批處理替代了逐個更新,這使得效能表現優異。
  • 持久性保障較弱因為新的資料最初只有單個副本。

(B) 對上面模式的一個改進是在任意一個節點收到更新資料請求的同時非同步發送更新給所有可用節點。這也被認為是定向的反熵。

 
  • 與純粹的反熵相比,這種做法只用一點小小的效能犧牲就極大地提高了一致性。然而,正式一致性和持久性保持不變。
  • 假如某些節點因為網路故障或是節點失效在當時是停用,更新最終也會通過反熵傳播過程來傳遞到該節點。

(C) 在前一個模式中,使用提示移交技術可以更好地處理某個節點的操作失敗。對於失效節點的預期更新被記錄在額外的代理節點上,並且標明一旦特點節點可用就要將更新傳遞給該節點。這樣做提高了一致性,降低了複製收斂時間。

(D, 一次性讀寫)因為提示移交的責任節點也有可能在將更新傳遞出去之前就已經失效,在這種情況下就有必要通過所謂的讀修複來保證一致性。每個讀操作都會啟動一個非同步過程,向儲存這條資料的所有節點請求一份資料摘要(像簽名或者hash),如果發現各節點返回的摘要不一致則統一各節點上的資料版本。我們用一次性讀寫來命名組合了A、B、C、D的技術- 他們都沒有提供嚴格的一致性保證,但是作為一個自備的方法已經可以用於實踐了。

(E, 讀若干寫若干) 上面的策略是降低了複製收斂時間的啟發學習法增強。為了保證更強的一致性,必須犧牲可用性來保證一定的讀寫重疊。 通常的做法是同時寫入W個副本而不是一個,讀的時候也要讀R個副本。

 
  • 首先,可以配置寫副本數W>1。
  • 其次,因為R+W>N,寫入的節點和讀取的節點之間必然會有重疊,所以讀取的多個資料副本裡至少會有一個是比較新的資料(上面的圖中 W=2, R=3, N=4 )。這樣在讀寫請求依序進行的時候(寫執行完再讀)能夠保證一致性(對於單個使用者的讀寫一致性),但是不能保障全域的讀一致性。用下面圖示裡的例子來看,R=2,W=2,N=3,因為寫操作對於兩個副本的更新是非事務的,在更新沒有完成的時候讀就可能讀到兩個都是舊值或者一新一舊:

 
  • 對於某種讀延遲的要求,設定R和W的不同值可以調整寫延遲與持久性,反之亦然。
  • 如果W<=N/2,並發的多個寫入會寫到不同的若干節點(如,寫操作A寫前N/2個,B寫後N/2個)。 設定 W>N/2 可以保證在符合復原模型的原子讀改寫時及時檢測到衝突。
  • 嚴格來講,這種模式雖然可以容忍個別節點的失效, 但是對於網路隔離的容錯性並不好。在實踐中,常使用”近似數量通過“這樣的方法,通過犧牲一致性來提高某些情景下的可用性。

(F, 讀全部寫若干)讀一致性問題可以通過在讀資料的時候訪問所有副本(讀資料或者檢查摘要)來減輕。這確保了只要有至少一個節點上的資料更新新的資料就能被讀取者看到。但是在網路隔離的情況下這種保證就不能起到作用了。

(G, 主從) 這種技術常被用來提供原子寫或者 衝突檢測持久層級的讀改寫。為了實現衝突預防層級,必須要用一種集中管理方式或者是鎖。最簡單的策略是用主從非同步複製。對於特定資料項目的寫操作全部被路由到一個中心節點,並在上面順序執行。這種情況下主節點會成為瓶頸,所以必須要將資料劃分成一個個獨立的片區(不同片有不同的master),這樣才能提供擴充性。

(H, Transactional Read Quorum Write Quorum and Read One Write All)  更新多個副本的方法可以通過使用事務控制技術來避免寫衝突。 眾所周知的方法是使用兩階段交易認可協議。但兩階段交易認可並不是完全可靠的,因為協調者失效可能會造成資源阻塞。 PAXOS提交協議是更可靠的選擇,但會損失一點效能。 在這個基礎上再向前一小步就是讀一個副本寫所有副本,這種方法把所有副本的更新放在一個事務中,它提供了強容錯一致性但會損失掉一些效能和可用性。

上面分析中的一些權衡有必要再強調一下
  • 一致性與可用性。 嚴密的權衡已經由CAP理論給出了。在網路隔離的情況下,資料庫要麼將資料集中,要麼既要接受資料丟失的風險。
  • 一致性與擴充性。 看得出即使讀寫一致性保證降低了複本集的擴充性,只有在原子寫模型中才可以以一種相對可擴充的方式處理寫衝突。原子讀改寫模型通過給資料加上臨時性的全域鎖來避免衝突。這表明, 資料或操作之間的依賴,即使是很小範圍內或很短時間的,也會損害擴充性。所以精心設計資料模型,將資料分區分開存放對於擴充性非常重要。
  • 一致性與延遲。 如上所述,當資料庫需要提供強一致性或者持久性的時候應該偏向於讀寫所有副本技術。但是很明顯一致性與請求延遲成反比,所以使用若干副本技術會是比較中允的辦法。
  • 容錯移轉與一致性/擴充性/延遲。有趣的是容錯性與一致性、擴充性、延遲的取捨衝突並不劇烈。通過合理的放棄一些效能與一致性,叢集可以容忍多達 up to 的節點失效。這種折中在兩階段交易認可與 PAXOS 協議的區別裡體現得很明顯。這種折中的另一個例子是增加特定的一致性保障,比如使用嚴格會話進程的“讀己所寫”,但這又增加了容錯移轉的複雜性。
反熵協議, 謠言傳播演算法

讓我們從以下情境開始:

有許多節點,每條資料會在其中的若干的節點上面存有副本。每個節點都可以單獨處理更新要求,每個節點定期和其他節點同步狀態,如此一段時間之後所有的副本都會趨向一致。同步過程是怎樣進行的?同步何時開始?怎樣選擇同步的對象?怎麼交換資料?我們假定兩個節點總是用較新版本的資料覆蓋舊的資料或者兩個版本都保留以待應用程式層處理。

這個問題常見於資料一致性維護和叢集狀態同步(如叢集成員資訊傳播)等情境。雖然引入一個監控資料庫並制定同步計劃的協調者可以解決這個問題,但是去中心化的資料庫能夠提供更好的容錯性。去中心化的主要做法是利用精心設計的傳染協議,這種協議相對簡單,但是提供了很好的收斂時間,而且能夠容忍任何節點的失效和網路隔離。儘管有許多類型的傳染演算法,我們只關注反熵協議,因為NoSQL資料庫都在使用它。

反熵協議假定同步會按照一個固定進度表執行,每個節點定期隨機或是按照某種規則選擇另外一個節點交換資料,消除差異。有三種反風格的反熵協議:推,拉和混合。推協議的原理是簡單選取一個隨機節點然後把資料狀態發送過去。在真實應用中將全部資料都推送出去顯然是愚蠢的,所以節點一般按照所示的方式工作。

節點A作為同步發起者準備好一份資料摘要,裡麵包含了A上資料的指紋。節點B接收到摘要之後將摘要中的資料與本機資料進行比較,並將資料差異做成一份摘要返回給A。最後,A發送一個更新給B,B再更新資料。拉方式和混合方式的協議與此類似,就如所示的。

反熵協議提供了足夠好的收斂時間和擴充性。展示了一個在100個節點的叢集中傳播一個更新的類比結果。在每次迭代中,每個節點只與一個隨機選取的對等節點發生聯絡。

可以看到,拉方式的收斂性比推方式更好,這可以從理論上得到證明。而且推方式還存在一個“收斂尾巴”的問題。在多次迭代之後,儘管幾乎遍曆到了所有的節點,但還是有很少的一部分沒受到影響。與單純的推和拉方式相比, 混合方式的效率更高,所以實際應用中通常使用這種方式。反熵是可擴充的,因為平均轉換時間以叢集規模的對數函數形式增長。

儘管這些技術看起來很簡單,仍然有許多研究關注於不同約束條件下反熵協議的效能表現。其中之一通過一種更有效結構使用網路拓撲來取代隨機選取 。在網路頻寬有限的條件下調整傳輸率或使用先進的規則來選取要同步的資料 。摘要計算也面臨挑戰,資料庫會維護一份最新動向的日誌以有助於摘要計算。

更多詳情見請繼續閱讀下一頁的精彩內容:

  • 1
  • 2
  • 3
  • 下一頁

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.