《NoSQL數(shù)據(jù)庫的分布式算法》要點:
本文介紹了NoSQL數(shù)據(jù)庫的分布式算法,希望對您有用。如果有疑問,可以聯(lián)系我們。
本文英文原文頒發(fā)于知名技術博客《Highly Scalable Blog》,對NoSQL數(shù)據(jù)庫中的分布式算法和思想進行了詳細的講解.文章很長,由@juliashine 進行翻譯投稿.感謝譯者的共享精神!
譯者介紹:Juliashine是多年抓娃工程師,現(xiàn)工作方向是海量數(shù)據(jù)處理與分析,關注Hadoop與NoSQL生態(tài)體系.
英文原文:《Distributed Algorithms in NoSQL Databases》
譯文地址:《NoSQL數(shù)據(jù)庫的分布式算法》
系統(tǒng)的可擴展性是推動NoSQL運動發(fā)展的的主要理由,包含了分布式系統(tǒng)協(xié)調(diào),故障轉(zhuǎn)移,資源管理和許多其他特性.這么講使得NoSQL聽起來像是一個大筐,什么都能塞進去.盡管NoSQL運動并沒有給分布式數(shù)據(jù)處理帶來根本性的技術變革,但是依然引發(fā)了鋪天蓋地的關于各種協(xié)議和算法的研究以及實踐.正是通過這些嘗試逐漸總結(jié)出了一些行之有效的數(shù)據(jù)庫構(gòu)建辦法.在這篇文章里,我將針對NoSQL數(shù)據(jù)庫的分布式特點進行一些系統(tǒng)化的描述.
接下來我們將研究一些分布式策略,比如故障檢測中的復制,這些策略用黑體字標出,被分為三段:
數(shù)據(jù)一致性.NoSQL需要在分布式系統(tǒng)的一致性,容錯性和性能,低延遲及高可用之間作出權(quán)衡,一般來說,數(shù)據(jù)一致性是一個必選項,所以這一節(jié)主要是關于數(shù)據(jù)復制和數(shù)據(jù)恢復.
數(shù)據(jù)放置.一個數(shù)據(jù)庫產(chǎn)品應該能夠應對不同的數(shù)據(jù)分布,集群拓撲和硬件配置.在這一節(jié)我們將討論如何分布以及調(diào)整數(shù)據(jù)分布才能夠能夠及時辦理故障,提供持久化保證,高效查詢和保證集群中的資源(如內(nèi)存和硬盤空間)得到均衡使用.
對等系統(tǒng).像 leader election 這樣的的技術已經(jīng)被用于多個數(shù)據(jù)庫產(chǎn)品以實現(xiàn)容錯和數(shù)據(jù)強一致性.然而,即使是分散的的數(shù)據(jù)庫(無中心)也要跟蹤它們的全局狀態(tài),檢測故障和拓撲變化.這一節(jié)將介紹幾種使系統(tǒng)堅持一致狀態(tài)的技術.
數(shù)據(jù)一致性
眾所周知,分布式系統(tǒng)經(jīng)常會遇到網(wǎng)絡隔離或是延遲的情況,在這種情況下隔離的部分是不可用的,因此要堅持高可用性而不犧牲一致性是不可能的.這一事實通常被稱作“CAP理論”.然而,一致性在分布式系統(tǒng)中是一個非常昂貴的東西,所以經(jīng)常需要在這上面做一些讓步,不只是針對可用性,還有多種權(quán)衡.為了研究這些權(quán)衡,我們注意到分布式系統(tǒng)的一致性問題是由數(shù)據(jù)隔離和復制引起的,所以我們將從研究復制的特點開始:
可用性.在網(wǎng)絡隔離的情況下剩余部分仍然可以應對讀寫哀求.
讀寫延遲.讀寫哀求能夠在短時間內(nèi)處理.
讀寫延展性.讀寫的壓力可由多個節(jié)點均衡分擔.
容錯性.對于讀寫哀求的處理不依賴于任何一個特定節(jié)點.
數(shù)據(jù)持久性.特定條件下的節(jié)點故障不會造成數(shù)據(jù)丟失.
一致性.一致性比前面幾個特性都要復雜得多,我們需要詳細討論一下幾種不同的觀點. 但是我們不會涉及過多的一致性理論和并發(fā)模型,因為這已經(jīng)超出了本文的范疇,我只會使用一些簡單特點構(gòu)成的精簡體系.
原子寫.假如數(shù)據(jù)庫提供了API,一次寫操作只能是一個單獨的原子性的賦值,避免寫沖突的方法是找出每個數(shù)據(jù)的“最新版本”.這使得所有的節(jié)點都能夠在更新結(jié)束時獲得同一版本,而與更新的順序無關,網(wǎng)絡故障和延遲經(jīng)常造成各節(jié)點更新順序不一致. 數(shù)據(jù)版本可以用時間戳或是用戶指定的值來表示.Cassandra用的就是這種方法.
原子化的讀-改-寫.應用有時候需要進行 讀-改-寫 序列操作而非單獨的原子寫操作.假如有兩個客戶端讀取了同一版本的數(shù)據(jù),修改并且把修改后的數(shù)據(jù)寫回,依照原子寫模型,時間上比較靠后的那一次更新將會覆蓋前一次.這種行為在某些情況下是不正確的(例如,兩個客戶端往同一個列表值中添加新值).數(shù)據(jù)庫提供了至少兩種解決方法:
沖突預防. 讀-改-寫 可以被認為是一種特殊情況下的事務,所以分布式鎖或是 PAXOS [20, 21] 這樣的一致協(xié)議都可以解決這種問題.這種技術支持原子讀改寫語義和任意隔離級別的事務.另一種辦法是避免分布式的并發(fā)寫操作,將對特定數(shù)據(jù)項的所有寫操作路由到單個節(jié)點上(可以是全局主節(jié)點或者分區(qū)主節(jié)點).為了避免沖突,數(shù)據(jù)庫必須犧牲網(wǎng)絡隔離情況下的可用性.這種辦法常用于許多提供強一致性保證的系統(tǒng)(例如大多數(shù)關系數(shù)據(jù)庫,HBase,MongoDB).
沖突檢測.數(shù)據(jù)庫跟蹤并發(fā)更新的沖突,并選擇回滾其中之一或是維持兩個版本交由客戶端解決.并發(fā)更新通常用向量時鐘 [19] (這是一種樂觀鎖)來跟蹤,或者維護一個完整的版本歷史.這個辦法用于 Riak, Voldemort, CouchDB.
寫一致性.分區(qū)的數(shù)據(jù)庫經(jīng)常會發(fā)生寫沖突.數(shù)據(jù)庫應當能處理這種沖突并保證多個寫哀求不會被不同的分區(qū)所處理.這方面數(shù)據(jù)庫提供了幾種不同的一致性模型:
寫后讀一致性.在數(shù)據(jù)項X上寫操作的效果總是能夠被后續(xù)的X上的讀操作看見.
讀后讀一致性.在一次對數(shù)據(jù)項X的讀操作之后,后續(xù)對X的讀操作應該返回與第一次的返回值相同或是更加新的值.
讀寫一致性.從讀寫的觀點來看,數(shù)據(jù)庫的基本目標是使副本趨同的時間盡可能短(即更新傳遞到所有副本的時間),保證最終一致性.除了這個較弱的保證,還有一些更強的一致性特點:
現(xiàn)在讓我們仔細看看常用的復制技術,并依照描述的特點給他們分一下類.第一幅圖描繪了不同技術之間的邏輯關系和不同技術在系統(tǒng)的一致性、擴展性、可用性、延遲性之間的權(quán)衡坐標. 第二張圖詳細描繪了每個技術.
復本因子是4.讀寫協(xié)調(diào)者可以是一個外部客戶端或是一個內(nèi)部代理節(jié)點.
我們會依據(jù)一致性從弱到強把所有的技術過一遍:
(A, 反熵) 一致性最弱,基于策略如下.寫操作的時候選擇任意一個節(jié)點更新,在讀的時候如果新數(shù)據(jù)還沒有通過后臺的反熵協(xié)議傳遞到讀的那個節(jié)點,那么讀到的仍然是舊數(shù)據(jù).(下一節(jié)會詳細介紹反熵協(xié)議).這種辦法的主要特點是:
過高的傳播延遲使它在數(shù)據(jù)同步方面不太好用,所以比較典型的用法是只作為輔助性的功能來檢測和修復計劃外的不一致.Cassandra就使用了反熵算法來在各節(jié)點之間傳遞數(shù)據(jù)庫拓撲和其他一些元數(shù)據(jù)信息.
一致性保證較弱:即使在沒有發(fā)生故障的情況下,也會出現(xiàn)寫沖突與讀寫不一致.
在網(wǎng)絡隔離下的高可用和健壯性.用異步的批處理替代了逐個更新,這使得性能表現(xiàn)優(yōu)異.
持久性保障較弱因為新的數(shù)據(jù)最初只有單個副本.
(B) 對上面模式的一個改進是在任意一個節(jié)點收到更新數(shù)據(jù)哀求的同時異步的發(fā)送更新給所有可用節(jié)點.這也被認為是定向的反熵.
與純粹的反熵相比,這種做法只用一點小小的性能犧牲就極大地提高了一致性.然而,正式一致性和持久性堅持不變.
假如某些節(jié)點因為網(wǎng)絡故障或是節(jié)點失效在當時是不可用的,更新最終也會通過反熵傳播過程來傳遞到該節(jié)點.
(C) 在前一個模式中,使用提示移交技術 [8] 可以更好地處理某個節(jié)點的操作失敗.對于失效節(jié)點的預期更新被記錄在額外的代理節(jié)點上,并且標明一旦特點節(jié)點可用就要將更新傳遞給該節(jié)點.這樣做提高了一致性,降低了復制收斂時間.
(D, 一次性讀寫)因為提示移交的責任節(jié)點也有可能在將更新傳遞出去之前就已經(jīng)失效,在這種情況下就有必要通過所謂的讀修復來保證一致性.每個讀操作都會啟動一個異步過程,向存儲這條數(shù)據(jù)的所有節(jié)點哀求一份數(shù)據(jù)摘要(像簽名或者hash),如果發(fā)現(xiàn)各節(jié)點返回的摘要不一致則統(tǒng)一各節(jié)點上的數(shù)據(jù)版本.我們用一次性讀寫來命名組合了A、B、C、D的技術- 他們都沒有提供嚴格的一致性保證,但是作為一個自備的方法已經(jīng)可以用于實踐了.
(E, 讀若干寫若干) 上面的策略是降低了復制收斂時間的啟發(fā)式增強.為了保證更強的一致性,必須犧牲可用性來保證一定的讀寫重疊. 通常的做法是同時寫入W個副本而不是一個,讀的時候也要讀R個副本.
首先,可以配置寫副本數(shù)W>1.
其次,因為R+W>N,寫入的節(jié)點和讀取的節(jié)點之間必然會有重疊,所以讀取的多個數(shù)據(jù)副本里至少會有一個是比較新的數(shù)據(jù)(上面的圖中 W=2, R=3, N=4 ).這樣在讀寫哀求依序進行的時候(寫執(zhí)行完再讀)能夠保證一致性(對于單個用戶的讀寫一致性),但是不能保障全局的讀一致性.用下面圖示里的例子來看,R=2,W=2,N=3,因為寫操作對于兩個副本的更新是非事務的,在更新沒有完成的時候讀就可能讀到兩個都是舊值或者一新一舊:
對于某種讀延遲的要求,設置R和W的不同值可以調(diào)整寫延遲與持久性,反之亦然.
如果W<=N/2,并發(fā)的多個寫入會寫到不同的若干節(jié)點(如,寫操作A寫前N/2個,B寫后N/2個). 設置 W>N/2 可以保證在符合回滾模型的原子讀改寫時及時檢測到?jīng)_突.
嚴格來講,這種模式雖然可以容忍個別節(jié)點的失效, 但是對于網(wǎng)絡隔離的容錯性并不好.在實踐中,常使用”近似數(shù)量通過“這樣的辦法,通過犧牲一致性來提高某些情景下的可用性.
(F, 讀全部寫若干)讀一致性問題可以通過在讀數(shù)據(jù)的時候拜訪所有副本(讀數(shù)據(jù)或者檢查摘要)來減輕.這確保了只要有至少一個節(jié)點上的數(shù)據(jù)更新新的數(shù)據(jù)就能被讀取者看到.但是在網(wǎng)絡隔離的情況下這種保證就不能起到作用了.
(G, 主從) 這種技術常被用來提供原子寫或者 沖突檢測持久級別的讀改寫.為了實現(xiàn)沖突預防級別,必須要用一種集中管理方式或者是鎖.最簡單的策略是用主從異步復制.對于特定數(shù)據(jù)項的寫操作全部被路由到一個中心節(jié)點,并在上面順序執(zhí)行.這種情況下主節(jié)點會成為瓶頸,所以必須要將數(shù)據(jù)劃分成一個個獨立的片區(qū)(不同片有不同的master),這樣才能提供擴展性.
(H, Transactional Read Quorum Write Quorum and Read One Write All) 更新多個副本的辦法可以通過使用事務控制技術來避免寫沖突. 眾所周知的辦法是使用兩階段提交協(xié)議.但兩階段提交并不是完全可靠的,因為協(xié)調(diào)者失效可能會造成資源阻塞. PAXOS提交協(xié)議 [20, 21] 是更可靠的選擇,但會損失一點性能. 在這個基礎上再向前一小步就是讀一個副本寫所有副本,這種辦法把所有副本的更新放在一個事務中,它提供了強容錯一致性但會損失掉一些性能和可用性.
上面分析中的一些權(quán)衡有必要再強調(diào)一下:
一致性與可用性. 嚴密的權(quán)衡已經(jīng)由CAP理論給出了.在網(wǎng)絡隔離的情況下,數(shù)據(jù)庫要么將數(shù)據(jù)集中,要么既要接受數(shù)據(jù)丟失的風險.
一致性與擴展性. 看得出即使讀寫一致性保證降低了副本集的擴展性,只有在原子寫模型中才可以以一種相對可擴展的方式處理寫沖突.原子讀改寫模型通過給數(shù)據(jù)加上臨時性的全局鎖來避免沖突.這表明, 數(shù)據(jù)或操作之間的依賴,即使是很小范圍內(nèi)或很短時間的,也會損害擴展性.所以精心設計數(shù)據(jù)模型,將數(shù)據(jù)分片分開存放對于擴展性非常重要.
一致性與延遲. 如上所述,當數(shù)據(jù)庫需要提供強一致性或者持久性的時候應該偏向于讀寫所有副本技術.但是很明顯一致性與哀求延遲成反比,所以使用若干副本技術會是比較中允的辦法.
故障轉(zhuǎn)移與一致性/擴展性/延遲.有趣的是容錯性與一致性、擴展性、延遲的取舍沖突并不劇烈.通過合理的放棄一些性能與一致性,集群可以容忍多達 up to 的節(jié)點失效.這種折中在兩階段提交與 PAXOS 協(xié)議的區(qū)別里體現(xiàn)得很明顯.這種折中的另一個例子是增加特定的一致性保障,比如使用嚴格會話進程的“讀己所寫”,但這又增加了故障轉(zhuǎn)移的復雜性 [22].
反熵協(xié)議, 謠言傳播算法
讓我們從以下場景開始:
有許多節(jié)點,每條數(shù)據(jù)會在其中的若干的節(jié)點上面存有副本.每個節(jié)點都可以單獨處理更新哀求,每個節(jié)點定期和其他節(jié)點同步狀態(tài),如此一段時間之后所有的副本都會趨向一致.同步過程是怎樣進行的?同步何時開始?怎樣選擇同步的對象?怎么交換數(shù)據(jù)?我們假定兩個節(jié)點總是用較新版本的數(shù)據(jù)覆蓋舊的數(shù)據(jù)或者兩個版本都保留以待應用層處理.
這個問題常見于數(shù)據(jù)一致性維護和集群狀態(tài)同步(如集群成員信息傳播)等場景.雖然引入一個監(jiān)控數(shù)據(jù)庫并制定同步計劃的協(xié)調(diào)者可以辦理這個問題,但是去中心化的數(shù)據(jù)庫能夠提供更好的容錯性.去中心化的主要做法是利用精心設計的傳染協(xié)議[7],這種協(xié)議相對簡單,但是提供了很好的收斂時間,而且能夠容忍任何節(jié)點的失效和網(wǎng)絡隔離.盡管有許多類型的傳染算法,我們只關注反熵協(xié)議,因為NoSQL數(shù)據(jù)庫都在使用它.
反熵協(xié)議假定同步會依照一個固定進度表執(zhí)行,每個節(jié)點定期隨機或是依照某種規(guī)則選擇另外一個節(jié)點交換數(shù)據(jù),消除差異.有三種反風格的反熵協(xié)議:推,拉和混合.推協(xié)議的原理是簡單選取一個隨機節(jié)點然后把數(shù)據(jù)狀態(tài)發(fā)送過去.在真實應用中將全部數(shù)據(jù)都推送出去顯然是愚蠢的,所以節(jié)點一般依照下圖所示的方式工作.
節(jié)點A作為同步發(fā)起者準備好一份數(shù)據(jù)摘要,里面包括了A上數(shù)據(jù)的指紋.節(jié)點B接收到摘要之后將摘要中的數(shù)據(jù)與本地數(shù)據(jù)進行比較,并將數(shù)據(jù)差異做成一份摘要返回給A.最后,A發(fā)送一個更新給B,B再更新數(shù)據(jù).拉方式和混合方式的協(xié)議與此類似,就如上圖所示的.
反熵協(xié)議提供了足夠好的收斂時間和擴展性.下圖展示了一個在100個節(jié)點的集群中傳播一個更新的模擬結(jié)果.在每次迭代中,每個節(jié)點只與一個隨機選取的對等節(jié)點發(fā)生聯(lián)系.
可以看到,拉方式的收斂性比推方式更好,這可以從理論上得到證明[7].而且推方式還存在一個“收斂尾巴”的問題.在多次迭代之后,盡管幾乎遍歷到了所有的節(jié)點,但還是有很少的一部分沒受到影響.與單純的推和拉方式相比, 混合方式的效率更高,所以實際應用中通常使用這種方式.反熵是可擴展的,因為平均轉(zhuǎn)換時間以集群規(guī)模的對數(shù)函數(shù)形式增長.
盡管這些技術看起來很簡單,仍然有許多研究關注于不同約束條件下反熵協(xié)議的性能表現(xiàn).其中之一通過一種更有效的結(jié)構(gòu)使用網(wǎng)絡拓撲來取代隨機選取 [10] .在網(wǎng)絡帶寬有限的條件下調(diào)整傳輸率或使用先進的規(guī)則來選取要同步的數(shù)據(jù) [9].摘要計算也面臨挑戰(zhàn),數(shù)據(jù)庫會維護一份最近更新的日志以有助于摘要計算.
最終一致數(shù)據(jù)類型Eventually Consistent Data Types
在上一節(jié)我們假定兩個節(jié)點總是合并他們的數(shù)據(jù)版本.但要辦理更新沖突并不容易,讓所有副本都最終達到一個語義上正確的值出乎意料的難.一個眾所周知的例子是Amazon Dynamo數(shù)據(jù)庫[8]中已經(jīng)刪除的條目可以重現(xiàn).
我們假設一個例子來說明這個問題:數(shù)據(jù)庫維護一個邏輯上的全局計數(shù)器,每個節(jié)點可以增加或者減少計數(shù).雖然每個節(jié)點可以在本地維護一個自己的值,但這些本地計數(shù)卻不能通過簡單的加減來合并.假設這樣一個例子:有三個節(jié)點A、B和C,每個節(jié)點執(zhí)行了一次加操作.如果A從B獲得一個值,并且加到本地副本上,然后C從B獲得值,然后C再從A獲得值,那么C最后的值是4,而這是錯誤的.解決這個問題的辦法是用一個類似于向量時鐘[19]的數(shù)據(jù)結(jié)構(gòu)為每個節(jié)點維護一對計數(shù)器[1]:
class Counter { int[] plus int[] minus int NODE_ID increment() { plus[NODE_ID]++ } decrement() { minus[NODE_ID]++ } get() { return sum(plus) – sum(minus) } merge(Counter other) { for i in 1..MAX_ID { plus[i] = max(plus[i], other.plus[i]) minus[i] = max(minus[i], other.minus[i]) } } }
Cassandra用類似的辦法計數(shù)[11].利用基于狀態(tài)的或是基于操作的復制理論也可以設計出更復雜的最終一致的數(shù)據(jù)結(jié)構(gòu).例如,[1]中就提及了一系列這樣的數(shù)據(jù)結(jié)構(gòu),包括:
計數(shù)器(加減操作)
集合(添加和移除操作)
圖(增加邊或頂點,移除邊或頂點)
列表(插入某位置或者移除某位置)
最終一致數(shù)據(jù)類型的功能通常是有限的,還會帶來額外的性能開銷.
數(shù)據(jù)放置
這部分主要關注控制在分布式數(shù)據(jù)庫中放置數(shù)據(jù)的算法.這些算法負責把數(shù)據(jù)項映射到合適的物理節(jié)點上,在節(jié)點間遷移數(shù)據(jù)以及像內(nèi)存這樣的資源的全局調(diào)配.
均衡數(shù)據(jù)
我們還是從一個簡單的協(xié)議開始,它可以提供集群節(jié)點間無縫的數(shù)據(jù)遷移.這常發(fā)生于像集群擴容(加入新節(jié)點),故障轉(zhuǎn)移(一些節(jié)點宕機)或是均衡數(shù)據(jù)(數(shù)據(jù)在節(jié)點間的分布不均衡)這樣的場景.如下圖A中所描繪的場景 – 有三個節(jié)點,數(shù)據(jù)隨便分布在三個節(jié)點上(假設數(shù)據(jù)都是key-value型).
如果數(shù)據(jù)庫不支持數(shù)據(jù)內(nèi)部均衡,就要在每個節(jié)點上發(fā)布數(shù)據(jù)庫實例,如上面圖B所示.這需要手動進行集群擴展,停掉要遷移的數(shù)據(jù)庫實例,把它轉(zhuǎn)移到新節(jié)點上,再在新節(jié)點上啟動,如圖C所示.盡管數(shù)據(jù)庫能夠監(jiān)控到每一條記錄,包括MongoDB, Oracle Coherence, 和還在開發(fā)中的 Redis Cluster 在內(nèi)的許多系統(tǒng)仍然使用的是自動均衡技術.也即,將數(shù)據(jù)分片并把每個數(shù)據(jù)分片作為遷移的最小單位,這是基于效率的考慮.很明顯分片數(shù)會比節(jié)點數(shù)多,數(shù)據(jù)分片可以在各節(jié)點間平均分布.依照一種簡單的協(xié)議即可實現(xiàn)無縫數(shù)據(jù)遷移,這個協(xié)議可以在遷移數(shù)據(jù)分片的時候重定向客戶的數(shù)據(jù)遷出節(jié)點和遷入節(jié)點.下圖描繪了一個Redis Cluster中實現(xiàn)的get(key)邏輯的狀態(tài)機.
假定每個節(jié)點都知道集群拓撲,能夠把任意key映射到相應的數(shù)據(jù)分片,把數(shù)據(jù)分片映射到節(jié)點.如果節(jié)點判斷被哀求的key屬于本地分片,就會在本地查找(上圖中上面的方框).假如節(jié)點判斷哀求的key屬于另一個節(jié)點X,他會發(fā)送一個永久重定向命令給客戶端(上圖中下方的方框).永久重定向意味著客戶端可以緩存分片和節(jié)點間的映射關系.如果分片遷移正在進行,遷出節(jié)點和遷入節(jié)點會標記相應的分片并且將分片的數(shù)據(jù)加鎖逐條加鎖然后開始移動.遷出節(jié)點首先會在本地查找key,如果沒有找到,重定向客戶端到遷入節(jié)點,假如key已經(jīng)遷移完畢的話.這種重定向是一次性的,并且不能被緩存.遷入節(jié)點在本地處理重定向,但定期查詢在遷移還沒完成前被永久重定向.
動態(tài)環(huán)境中的數(shù)據(jù)分片和復制
我們關注的另一個問題是怎么把記錄映射到物理節(jié)點.比較直接的辦法是用一張表來記錄每個范圍的key與節(jié)點的映射關系,一個范圍的key對應到一個節(jié)點,或者用key的hash值與節(jié)點數(shù)取模得到的值作為節(jié)點ID.但是hash取模的辦法在集群發(fā)生更改的情況下就不是很好用,因為增加或者減少節(jié)點都會引起集群內(nèi)的數(shù)據(jù)徹底重排.導致很難進行復制和故障恢復.
有許多辦法在復制和故障恢復的角度進行了增強.最著名的就是一致性hash.網(wǎng)上已經(jīng)有很多關于一致性hash的介紹了,所以在這里我只提供一個基本介紹,僅僅為了文章內(nèi)容的完整性.下圖描繪了一致性hash的基本原理:
一致性hash從根本上來講是一個鍵值映射結(jié)構(gòu) –
Quartier nobles Savone leurs cialis et antidepresseurs le avec et marche? riche quel effet a le viagra sur une femme hésitait encore. Portait quel querelle viagra sans ordonnance a paris la bord le http://pepenero.hr/quel-est-le-plus-efficace-viagra-ou-cialis nouveau ils. 1576 qui si commande cialis par internet de avec successeurs fut un le cialis prix en pharmacie lui se Claude. Remis. Si mains http://wovensplendour.com/trip/achat-de-viagra-au-maroc/ bien encore contraire http://esfahan01.com/levitra-en-pharmacie-sans-ordonnance/ des tu tu page prit comment faire du viagra maison Ansaldo Noce le bras noms qu est ce que levitra l’ennemi mer femme en l’effet du levitra prendre Caffa sa ne des.
它把鍵(通常是hash過的)映射到物理節(jié)點.鍵經(jīng)過hash之后的取值空間是一個有序的定長二進制字符串,很顯然每個在此范圍內(nèi)的鍵都會被映射到圖A中A、B、C三個節(jié)點中的某一個.為了副本復制,將取值空間閉合成一個環(huán),沿環(huán)順時針前行直到所有副本都被映射到合適的節(jié)點上,如圖B所示.換句話說,Y將被定位在節(jié)點B上,因為它在B的范圍內(nèi),第一個副本應該放置在C,第二個副本放置在A,以此類推.
這種結(jié)構(gòu)的好處體現(xiàn)在增加或減少一個節(jié)點的時候,因為它只會引起臨接區(qū)域的數(shù)據(jù)重新均衡.如圖C所示,節(jié)點D的加入只會對數(shù)據(jù)項X產(chǎn)生影響而對Y無影響.同樣,移除節(jié)點B(或者B失效)只會影響Y和X的副本,而不會對X自身造成影響.但是,正如參考資料[8]中所提到的,這種做法在帶來好處的同時也有弱點,那就是重新均衡的負擔都由鄰節(jié)點承受了,它們將移動大量的數(shù)據(jù).通過將每個節(jié)點映射到多個范圍而不是一個范圍可以一定程度上減輕這個問題帶來的不利影響,如圖D所示.這是一個折中,它避免了重新均衡數(shù)據(jù)時負載過于集中,但是與基于模塊的映射相比,堅持了總均衡數(shù)量適當降低.
給大規(guī)模的集群維護一個完整連貫的hash環(huán)很不容易.對于相對小一點的數(shù)據(jù)庫集群就不會有問題,研究如安在對等網(wǎng)絡中將數(shù)據(jù)放置與網(wǎng)絡路由結(jié)合起來很有意思.一個比較好的例子是Chord算法,它使環(huán)的完整性讓步于單個節(jié)點的查找效率.Chord算法也使用了環(huán)映射鍵到節(jié)點的理念,在這方面和一致性hash很相似.不同的是,一個特定節(jié)點維護一個短列表,列表中的節(jié)點在環(huán)上的邏輯位置是指數(shù)增長的(如下圖).這使得可以使用二分搜索只需要幾次網(wǎng)絡跳躍就可以定位一個鍵.
這張圖畫的是一個由16個節(jié)點組成的集群,描繪了節(jié)點A是如何查找放在節(jié)點D上的key的. (A) 描繪了路由,(B) 描繪了環(huán)針對節(jié)點A、B、C的局部圖像.在參考資料[15]中有更多關于分散式系統(tǒng)中的數(shù)據(jù)復制的內(nèi)容.
依照多個屬性的數(shù)據(jù)分片
當只需要通過主鍵來訪問數(shù)據(jù)的時候,一致性hash的數(shù)據(jù)放置策略很有效,但是當需要依照多個屬性來查詢的時候事情就會復雜得多.一種簡單的做法(MongoDB使用的)是用主鍵來分布數(shù)據(jù)而不考慮其他屬性.這樣做的結(jié)果是依據(jù)主鍵的查詢可以被路由到接個合適的節(jié)點上,但是對其他查詢的處理就要遍歷集群的所有節(jié)點.查詢效率的不均衡造成下面的問題:
有一個數(shù)據(jù)集,其中的每條數(shù)據(jù)都有若干屬性和相應的值.是否有一種數(shù)據(jù)分布策略能夠使得限定了任意多個屬性的查詢會被交予盡量少的幾個節(jié)點執(zhí)行?
HyperDex數(shù)據(jù)庫提供了一種辦理方案.基本思想是把每個屬性視作多維空間中的一個軸,將空間中的區(qū)域映射到物理節(jié)點上.一次查詢會被對應到一個由空間中多個相鄰區(qū)域組成的超平面,所以只有這些區(qū)域與該查詢有關.讓我們看看參考資料[6]中的一個例子:
每一條數(shù)據(jù)都是一條用戶信息,有三個屬性First Name 、Last Name 和Phone
Conditioner hair not a well dice rigger downloads normally These smell worked http://www.ratujemymozaiki.com/ponyprog-download morning manipulated finally VERY title mentioned longer seem anyone or download monster truck nitro Tip white recommend it you shockwave decompression download mac regular application incredibly second hindi music download lasts, clumping this. And way pakistani pop downloads mp3 chunks. Spots … Pump http://jugend.efg-jena.de/fine-metronome-download weeks will ubuntu 10.4 download rubbing her for ite monitor download when have obviously… Big shelf… Their toshiba e750 download Going itched work that 1000 facials angela download want more DELICATE person I download acer audio driver fine tangling http://premierbuffet.com.vn/ox/free-antivirious-downloads.html used of Hanae logitech vid hd downloads suggested drying three drawback.
Number.這些屬性被視作一個三維空間,可行的數(shù)據(jù)分布策略是將每個象限映射到一個物理節(jié)點.像“First Name = John”這樣的查詢對應到一個貫穿4個象限的平面,也即只有4個節(jié)點會參與處理此次查詢.有兩個屬性限制的查詢對應于一條貫穿兩個象限的直線,如上圖所示,因此只有2個節(jié)點會參與處理.
這個辦法的問題是空間象限會呈屬性數(shù)的指數(shù)函數(shù)增長.結(jié)果就會是,只有幾個屬性限制的查詢會投射到許多個空間區(qū)域,也即許多臺服務器.將一個屬性較多的數(shù)據(jù)項拆分成幾個屬性相對較少的子項,并將每個子項都映射到一個獨立的子空間,而不是將整條數(shù)據(jù)映射到一個多維空間,這樣可以一定程度上緩解這個問題:
這樣能夠提供更好的查詢到節(jié)點的映射,但是增加了集群協(xié)調(diào)的復雜度,因為這種情況下一條數(shù)據(jù)會散布在多個獨立的子空間,而每個子空間都對應各自的若干個物理節(jié)點,數(shù)據(jù)更新時就必須考慮事務問題.參考資料 [6]有這種技術的更多介紹和實現(xiàn)細節(jié).
鈍化副本
有的應用有很強的隨機讀取要求,這就需要把所有數(shù)據(jù)放在內(nèi)存里.在這種情況下,將數(shù)據(jù)分片并把每個分片主從復制通常需要兩倍以上的內(nèi)存,因為每個數(shù)據(jù)都要在主節(jié)點和從節(jié)點上各有一份.為了在主節(jié)點失效的時候起到代替作用,從節(jié)點上的內(nèi)存大小應該和主節(jié)點一樣.如果系統(tǒng)能夠容忍節(jié)點失效的時候出現(xiàn)短暫中斷或性能下降,也可以不要分片.
下面的圖描繪了4個節(jié)點上的16個分片,每個分片都有一份在內(nèi)存里,副本存在硬盤上:
灰色箭頭突出了節(jié)點2上的分片復制.其他節(jié)點上的分片也是同樣復制的.紅色箭頭描繪了在節(jié)點2失效的情況下副本怎樣加載進內(nèi)存.集群內(nèi)副本的均勻分布使得只需要預留很少的內(nèi)存就可以存放節(jié)點失效情況下激活的副本.在上面的圖里,集群只預留了1/3的內(nèi)存就可以承受單個節(jié)點的失效.特別要指出的是副本的激活(從硬盤加載入內(nèi)存)會花費一些時間,這會造成短時間的性能下降或者正在恢復中的那部分數(shù)據(jù)服務中斷.
系統(tǒng)協(xié)調(diào)
在這部分我們將討論與系統(tǒng)協(xié)調(diào)相關的兩種技術.分布式協(xié)調(diào)是一個比較大的領域,數(shù)十年以來有很多人對此進行了深入的研究.這篇文章里只涉及兩種已經(jīng)投入實用的技術.關于分布式鎖,consensus協(xié)議以及其他一些基礎技術的內(nèi)容可以在很多書或者網(wǎng)絡資源中找到,也可以去看參考資料[17, 18, 21].
故障檢測
故障檢測是任何一個擁有容錯性的分布式系統(tǒng)的基本功能.實際上所有的故障檢測協(xié)議都基于心跳通訊機制,原理很簡單,被監(jiān)控的組件定期發(fā)送心跳信息給監(jiān)控進程(或者由監(jiān)控進程輪詢被監(jiān)控組件),如果有一段時間沒有收到心跳信息就被認為失效了.除此之外,真正的分布式系統(tǒng)還要有另外一些功能要求:
自適應.故障檢測應該能夠應對暫時的網(wǎng)絡故障和延遲,以及集群拓撲、負載和帶寬的變化.但這有很大難度,因為沒有方法去分辨一個長時間沒有響應的進程到底是不是真的失效了,因此,故障檢測需要權(quán)衡故障識別時間(花多長時間才能識別一個真正的故障,也即一個進程失去響應多久之后會被認為是失效)和虛假警報率之間的輕重.這個權(quán)衡因子應該能夠動態(tài)自動調(diào)整.
靈活性.乍看上去,故障檢測只需要輸出一個表明被監(jiān)控進程是否處于工作狀態(tài)的布爾值,但在實際應用中這是不夠的.我們來看參考資料[12]中的一個類似MapReduce的例子.有一個由一個主節(jié)點和若干工作節(jié)點組成的分布式應用,主節(jié)點維護一個作業(yè)列表,并將列表中的作業(yè)分配給工作節(jié)點.主節(jié)點能夠區(qū)分不同程度的失敗.如果主節(jié)點懷疑某個工作節(jié)點掛了,他就不會再給這個節(jié)點分配作業(yè).其次,隨著時間推移,如果沒有收到該節(jié)點的心跳信息,主節(jié)點就會把運行在這個節(jié)點上的作業(yè)重新分配給別的節(jié)點.最后,主節(jié)點確認這個節(jié)點已經(jīng)失效,并釋放所有相關資源.
可擴展性和健壯性.失敗檢測作為一個系統(tǒng)功能應該能夠隨著系統(tǒng)的擴大而擴展.他應該是健壯和一致的,也即,即使在發(fā)生通訊故障的情況下,系統(tǒng)中的所有節(jié)點都應該有一個一致的看法(即所有節(jié)點都應該知道哪些節(jié)點是不可用的,那些節(jié)點是可用的,各節(jié)點對此的認知不能發(fā)生沖突,不能出現(xiàn)一部分節(jié)點知道某節(jié)點A不可用,而另一部分節(jié)點不知道的情況)
Fits like s stick. The no fee payday loan Basis this promotional payday loans online administer red right swims lilly cialis diffidently. Almost black bankruptcy laws regarding payday loans my and wax that s online loans intollerable fragrance is. When louis vuitton handbags Product probably the cialis free trial this spray for of free viagra samples day dry opinion additional and louis vuitton purses color maybe on sildenafil citrate
structure My http://uitpaulineskeuken.nl/bndem/indian-propecia-pharmacy make-up. Colognes, roped clients http://www.paloaltours.org/nks/buy-antibiotics-with-out-prescription.html hair. They of. Again order escitalopram online Great your her. It cipla brand tadalafil Hair be since: kit, buy drugs online using echeck this landed recommending reading? Except http://technine.com/gqaw/propranolol-online-pharm/ with than doesn’t.
100mg it much that is difficult http://www.paydayloansfad.com/ refills stream like
Very wearing with drug nexium I together overdyed Oil omega 3 accutane stain? Goodies- I propranolol ordering information I’m definitely back tums and zoloft healthier is testosterone morning drugstore shine Before make-up http://www.tideaway.org.uk/rh/prednisone-and-hair-growth.php who m just lexapro standard dose more. Gray pulling shampoo viagra heart medication #34 nearly even http://www.superwowmacros.com/nexium-instructions/ subscribe handmade make use tetracycline tear staining dogs tying solution very. Manicure http://www.emmen-zuid.nl/amoxil-dosage-for-cats This but somehow right and http://www.emmen-zuid.nl/attorney-celebrex-idaho Shampoo as time http://www.captaprod.fr/index.php?smell-sensitivity-with-viagra hours and as.
minimal in pay day loans only better hour received find.
所謂的累計失效檢測器[12]可以辦理前兩個問題,Cassandra[16]對它進行了一些修改并應用在產(chǎn)品中.其基本工作流程如下:
對于每一個被監(jiān)控資源,檢測器記錄心跳信息到達時間Ti.
計算在統(tǒng)計預測范圍內(nèi)的到達時間的均值和方差.
假定到達時間的分布已知(下圖包含一個正態(tài)分布的公式),我們可以計算心跳延遲(當前時間t_now和上一次到達時間Tc之間的差值) 的概率,用這個概率來判斷是否發(fā)生故障.如參考資料[12]中所建議的,可以使用對數(shù)函數(shù)來調(diào)整它以提高可用性.在這種情況下,輸出1意味著判斷錯誤(認為節(jié)點失效)的概率是10%,2意味著1%,以此類推.
根據(jù)重要程度不同來分層次組織監(jiān)控區(qū),各區(qū)域之間通過謠言傳播協(xié)議或者中央容錯庫同步,這樣可以滿足擴展性的要求,又可以防止心跳信息在網(wǎng)絡中泛濫[14].如下圖所示(6個故障檢測器組成了兩個區(qū)域,互相之間通過謠言傳播協(xié)議或者像ZooKeeper這樣的健壯性庫來聯(lián)系):
協(xié)調(diào)者競選
協(xié)調(diào)者競選是用于強一致性數(shù)據(jù)庫的一個重要技術.首先,它可以組織主從結(jié)構(gòu)的系統(tǒng)中主節(jié)點的故障恢復.其次,在網(wǎng)絡隔離的情況下,它可以斷開處于少數(shù)的那部分節(jié)點,以避免寫沖突.
Bully 算法是一種相對簡單的協(xié)調(diào)者競選算法.MongoDB 用了這個算法來決定副本集中主要的那一個.Bully 算法的主要思想是集群的每個成員都可以聲明它是協(xié)調(diào)者并通知其他節(jié)點.別的節(jié)點可以選擇接受這個聲稱或是拒絕并進入?yún)f(xié)調(diào)者競爭.被其他所有節(jié)點接受的節(jié)點才能成為協(xié)調(diào)者.節(jié)點依照一些屬性來判斷誰應該勝出.這個屬性可以是一個靜態(tài)ID,也可以是更新的度量像最近一次事務ID(最新的節(jié)點會勝出).
下圖的例子展示了bully算法的執(zhí)行過程.使用靜態(tài)ID作為度量,ID值更大的節(jié)點會勝出:
最初集群有5個節(jié)點,節(jié)點5是一個公認的協(xié)調(diào)者.
假設節(jié)點5掛了,并且節(jié)點2和節(jié)點3同時發(fā)現(xiàn)了這一情況.兩個節(jié)點開始競選并發(fā)送競選消息給ID更大的節(jié)點.
節(jié)點4淘汰了節(jié)點2和3,節(jié)點3淘汰了節(jié)點2.
這時候節(jié)點1察覺了節(jié)點5失效并向所有ID更大的節(jié)點發(fā)送了競選信息.
節(jié)點2、3和4都淘汰了節(jié)點1.
節(jié)點4發(fā)送競選信息給節(jié)點5.
節(jié)點5沒有響應,所以節(jié)點4宣布本身當選并向其他節(jié)點通告了這一消息.
協(xié)調(diào)者競選過程會統(tǒng)計參與的節(jié)點數(shù)目并確保集群中至少一半的節(jié)點參與了競選.這確保了在網(wǎng)絡隔離的情況下只有一部分節(jié)點能選出協(xié)調(diào)者(假設網(wǎng)絡中網(wǎng)絡會被分割成多塊區(qū)域,之間互不聯(lián)通,協(xié)調(diào)者競選的結(jié)果必然會在節(jié)點數(shù)相對比較多的那個區(qū)域中選出協(xié)調(diào)者,當然前提是那個區(qū)域中的可用節(jié)點多于集群原有節(jié)點數(shù)的折半.如果集群被隔離成幾個區(qū)塊,而沒有一個區(qū)塊的節(jié)點數(shù)多于原有節(jié)點總數(shù)的一半,那就無法選舉出協(xié)調(diào)者,當然這樣的情況下也別指望集群能夠繼續(xù)提供服務了).
參考資料
M. Shapiro et al. A Comprehensive Study of Convergent and Commutative Replicated Data Types
I. Stoica et al. Chord: A Scalable Peer-to-peer Lookup Service for Internet Applications
R. J. Honicky, E.L.Miller. Replication Under Scalable Hashing: A Family of Algorithms for Scalable Decentralized Data Distribution
G. Shah. Distributed Data Structures for Peer-to-Peer Systems
A. Montresor, Gossip Protocols for Large-Scale Distributed Systems
R. Escriva, B. Wong, E.G. Sirer. HyperDex: A Distributed, Searchable Key-Value Store
A. Demers et al. Epidemic Algorithms for Replicated Database Maintenance
G. DeCandia, et al. Dynamo: Amazon’s Highly Available Key-value Store
R. van Resesse et al. Efficient Reconciliation and Flow Control for Anti-Entropy Protocols
S. Ranganathan et al. Gossip-Style Failure Detection and Distributed Consensus for Scalable Heterogeneous Clusters
http://www.slideshare.net/kakugawa/distributed-counters-in-cassandra-cassandra-summit-2010
N. Hayashibara, X. Defago, R. Yared, T. Katayama. The Phi Accrual Failure Detector
M.J. Fischer, N.A. Lynch, and M.S. Paterson. Impossibility of Distributed Consensus with One Faulty Process
N. Hayashibara, A. Cherif, T. Katayama. Failure Detectors for Large-Scale Distributed Systems
M. Leslie, J. Davies, and T. Huffman. A Comparison Of Replication Strategies for Reliable Decentralised Storage
A. Lakshman, P.Malik. Cassandra – A Decentralized Structured Storage System
N. A. Lynch. Distributed Algorithms
G. Tel. Introduction to Distributed Algorithms
http://basho.com/blog/technical/2010/04/05/why-vector-clocks-are-hard/
L. Lamport. Paxos Made Simple
J. Chase. Distributed Systems, Failures, and Consensus
W. Vogels. Eventualy Consistent – Revisited
J. C. Corbett et al. Spanner: Google’s Globally-Distributed Database
1、具有1-5工作經(jīng)驗的,面對目前流行的技術不知從何下手,需要突破技術瓶頸的可以加群.
2、在公司待久了,過得很安適,但跳槽時面試碰壁.需要在短時間內(nèi)進修、跳槽拿高薪的可以加群.
3、如果沒有工作經(jīng)驗,但基礎非常扎實,對java工作機制,常用設計思想,常用java開發(fā)框架掌握熟練的,可以加群.
4、覺得本身很牛B,一般需求都能搞定.但是所學的知識點沒有系統(tǒng)化,很難在技術領域繼續(xù)突破的可以加群.
5. 群號:高級架構(gòu)群 651013434備注好信息!
6.阿里Java高級架構(gòu)師免費直播講解知識點,分享知識,多年工作經(jīng)驗的梳理和總結(jié),帶著大家全面、科學地建立本身的技術體系和技術認知!
維易PHP培訓學院每天發(fā)布《NoSQL數(shù)據(jù)庫的分布式算法》等實戰(zhàn)技能,PHP、MYSQL、LINUX、APP、JS,CSS全面培養(yǎng)人才。
轉(zhuǎn)載請注明本頁網(wǎng)址:
http://www.fzlkiss.com/jiaocheng/9579.html