国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|數(shù)據(jù)庫技術|

服務器之家 - 數(shù)據(jù)庫 - 數(shù)據(jù)庫技術 - NoSQL數(shù)據(jù)庫的分布式算法詳解

NoSQL數(shù)據(jù)庫的分布式算法詳解

2021-10-25 15:54數(shù)據(jù)庫技術網 數(shù)據(jù)庫技術

系統(tǒng)的可擴展性是推動NoSQL運動發(fā)展的的主要理由,包含了分布式系統(tǒng)協(xié)調,故障轉移,資源管理和許多其他特性。盡管NoSQL運動并沒有給分布式數(shù)據(jù)處理帶來根本性的技術變革,但是依然引發(fā)了鋪天蓋地的關于各種協(xié)議和算法的研

今天,我們將研究一些分布式策略,比如故障檢測中的復制,這些策略用黑體字標出,被分為三段:

  • 數(shù)據(jù)一致性。nosql需要在分布式系統(tǒng)的一致性,容錯性和性能,低延遲及高可用之間作出權衡,一般來說,數(shù)據(jù)一致性是一個必選項,所以這一節(jié)主要是關于 數(shù)據(jù)復制 和 數(shù)據(jù)恢復 。
  • 數(shù)據(jù)放置。一個數(shù)據(jù)庫產品應該能夠應對不同的數(shù)據(jù)分布,集群拓撲和硬件配置。在這一節(jié)我們將討論如何 分布 以及 調整數(shù)據(jù)分布 才能夠能夠及時解決故障,提供持久化保證,高效查詢和保證集訓中的資源(如內存和硬盤空間)得到均衡使用。
  • 對等系統(tǒng)。像 leader election 這樣的的技術已經被用于多個數(shù)據(jù)庫產品以實現(xiàn)容錯和數(shù)據(jù)強一致性。然而,即使是分散的的數(shù)據(jù)庫(無中心)也要跟蹤它們的全局狀態(tài),檢測故障和拓撲變化。這一節(jié)將介紹幾種使系統(tǒng)保持一致狀態(tài)的技術。system coordination. coordination techniques like leader election are used in

數(shù)據(jù)一致性

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

  • 可用性。在網絡隔離的情況下剩余部分仍然可以應對讀寫請求。
  • 讀寫延遲。讀寫請求能夠在短時間內處理。
  • 讀寫延展性。讀寫的壓力可由多個節(jié)點均衡分擔。
  • 容錯性。對于讀寫請求的處理不依賴于任何一個特定節(jié)點。
  • 數(shù)據(jù)持久性。特定條件下的節(jié)點故障不會造成數(shù)據(jù)丟失。

一致性。一致性比前面幾個特性都要復雜得多,我們需要詳細討論一下幾種不同的觀點。 但是我們不會涉及過多的一致性理論和并發(fā)模型,因為這已經超出了本文的范疇,我只會使用一些簡單特點構成的精簡體系。

讀寫一致性。從讀寫的觀點來看,數(shù)據(jù)庫的基本目標是使副本趨同的時間盡可能短(即更新傳遞到所有副本的時間),保證最終一致性。除了這個較弱的保證,還有一些更強的一致性特點:

寫后讀一致性。在數(shù)據(jù)項x上寫操作的效果總是能夠被后續(xù)的x上的讀操作看見。

讀后讀一致性。在一次對數(shù)據(jù)項x的讀操作之后,后續(xù)對x的讀操作應該返回與第一次的返回值相同或是更加新的值。

寫一致性。分區(qū)的數(shù)據(jù)庫經常會發(fā)生寫沖突。數(shù)據(jù)庫應當能處理這種沖突并保證多個寫請求不會被不同的分區(qū)所處理。這方面數(shù)據(jù)庫提供了幾種不同的一致性模型:

原子寫。假如數(shù)據(jù)庫提供了api,一次寫操作只能是一個單獨的原子性的賦值,避免寫沖突的辦法是找出每個數(shù)據(jù)的“最新版本”。這使得所有的節(jié)點都能夠在更新結束時獲得同一版本,而與更新的順序無關,網絡故障和延遲經常造成各節(jié)點更新順序不一致。 數(shù)據(jù)版本可以用時間戳或是用戶指定的值來表示。cassandra用的就是這種方法。

原子化的讀-改-寫。應用有時候需要進行 讀-改-寫 序列操作而非單獨的原子寫操作。假如有兩個客戶端讀取了同一版本的數(shù)據(jù),修改并且把修改后的數(shù)據(jù)寫回,按照原子寫模型,時間上比較靠后的那一次更新將會覆蓋前一次。這種行為在某些情況下是不正確的(例如,兩個客戶端往同一個列表值中添加新值)。數(shù)據(jù)庫提供了至少兩種解決方法:

沖突預防。 讀-改-寫 可以被認為是一種特殊情況下的事務,所以分布式鎖或是 paxos [20, 21] 這樣的一致協(xié)議都可以解決這種問題。這種技術支持原子讀改寫語義和任意隔離級別的事務。另一種方法是避免分布式的并發(fā)寫操作,將對特定數(shù)據(jù)項的所有寫操作路由到單個節(jié)點上(可以是全局主節(jié)點或者分區(qū)主節(jié)點)。為了避免沖突,數(shù)據(jù)庫必須犧牲網絡隔離情況下的可用性。這種方法常用于許多提供強一致性保證的系統(tǒng)(例如大多數(shù)關系數(shù)據(jù)庫,hbase,mongodb)。

沖突檢測。數(shù)據(jù)庫跟蹤并發(fā)更新的沖突,并選擇回滾其中之一或是維持兩個版本交由客戶端解決。并發(fā)更新通常用向量時鐘 [19] (這是一種樂觀鎖)來跟蹤,或者維護一個完整的版本歷史。這個方法用于 riak, voldemort, couchdb.

現(xiàn)在讓我們仔細看看常用的復制技術,并按照描述的特點給他們分一下類。第一幅圖描繪了不同技術之間的邏輯關系和不同技術在系統(tǒng)的一致性、擴展性、可用性、延遲性之間的權衡坐標。 第二張圖詳細描繪了每個技術。

NoSQL數(shù)據(jù)庫的分布式算法詳解

NoSQL數(shù)據(jù)庫的分布式算法詳解

復本因子是4。讀寫協(xié)調者可以是一個外部客戶端或是一個內部代理節(jié)點。

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

(a, 反熵) 一致性最弱,基于策略如下。寫操作的時候選擇任意一個節(jié)點更新,在讀的時候如果新數(shù)據(jù)還沒有通過后臺的反熵協(xié)議傳遞到讀的那個節(jié)點,那么讀到的仍然是舊數(shù)據(jù)。(下一節(jié)會詳細介紹反熵協(xié)議)。這種方法的主要特點是:

過高的傳播延遲使它在數(shù)據(jù)同步方面不太好用,所以比較典型的用法是只作為輔助性的功能來檢測和修復計劃外的不一致。cassandra就使用了反熵算法來在各節(jié)點之間傳遞數(shù)據(jù)庫拓撲和其他一些元數(shù)據(jù)信息。

一致性保證較弱:即使在沒有發(fā)生故障的情況下,也會出現(xiàn)寫沖突與讀寫不一致。

在網絡隔離下的高可用和健壯性。用異步的批處理替代了逐個更新,這使得性能表現(xiàn)優(yōu)異。

持久性保障較弱因為新的數(shù)據(jù)最初只有單個副本。

(b) 對上面模式的一個改進是在任意一個節(jié)點收到更新數(shù)據(jù)請求的同時異步的發(fā)送更新給所有可用節(jié)點。這也被認為是定向的反熵。

與純粹的反熵相比,這種做法只用一點小小的性能犧牲就極大地提高了一致性。然而,正式一致性和持久性保持不變。

假如某些節(jié)點因為網絡故障或是節(jié)點失效在當時是不可用的,更新最終也會通過反熵傳播過程來傳遞到該節(jié)點。

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

(d, 一次性讀寫)因為提示移交的責任節(jié)點也有可能在將更新傳遞出去之前就已經失效,在這種情況下就有必要通過所謂的讀修復來保證一致性。每個讀操作都會啟動一個異步過程,向存儲這條數(shù)據(jù)的所有節(jié)點請求一份數(shù)據(jù)摘要(像簽名或者hash),如果發(fā)現(xiàn)各節(jié)點返回的摘要不一致則統(tǒng)一各節(jié)點上的數(shù)據(jù)版本。我們用一次性讀寫來命名組合了a、b、c、d的技術- 他們都沒有提供嚴格的一致性保證,但是作為一個自備的方法已經可以用于實踐了。

(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,因為寫操作對于兩個副本的更新是非事務的,在更新沒有完成的時候讀就可能讀到兩個都是舊值或者一新一舊:

NoSQL數(shù)據(jù)庫的分布式算法詳解

對于某種讀延遲的要求,設置r和w的不同值可以調整寫延遲與持久性,反之亦然。

如果w<=n/2,并發(fā)的多個寫入會寫到不同的若干節(jié)點(如,寫操作a寫前n/2個,b寫后n/2個)。 設置 w>n/2 可以保證在符合回滾模型的原子讀改寫時及時檢測到沖突。

嚴格來講,這種模式雖然可以容忍個別節(jié)點的失效, 但是對于網絡隔離的容錯性并不好。在實踐中,常使用”近似數(shù)量通過“這樣的方法,通過犧牲一致性來提高某些情景下的可用性。

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

(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é)調者失效可能會造成資源阻塞。 paxos提交協(xié)議 [20, 21] 是更可靠的選擇,但會損失一點性能。 在這個基礎上再向前一小步就是讀一個副本寫所有副本,這種方法把所有副本的更新放在一個事務中,它提供了強容錯一致性但會損失掉一些性能和可用性。

上面分析中的一些權衡有必要再強調一下:

一致性與可用性。 嚴密的權衡已經由cap理論給出了。在網絡隔離的情況下,數(shù)據(jù)庫要么將數(shù)據(jù)集中,要么既要接受數(shù)據(jù)丟失的風險。
一致性與擴展性。 看得出即使讀寫一致性保證降低了副本集的擴展性,只有在原子寫模型中才可以以一種相對可擴展的方式處理寫沖突。原子讀改寫模型通過給數(shù)據(jù)加上臨時性的全局鎖來避免沖突。這表明, 數(shù)據(jù)或操作之間的依賴,即使是很小范圍內或很短時間的,也會損害擴展性。所以精心設計數(shù)據(jù)模型,將數(shù)據(jù)分片分開存放對于擴展性非常重要。
一致性與延遲。 如上所述,當數(shù)據(jù)庫需要提供強一致性或者持久性的時候應該偏向于讀寫所有副本技術。但是很明顯一致性與請求延遲成反比,所以使用若干副本技術會是比較中允的辦法。
故障轉移與一致性/擴展性/延遲。 有趣的是容錯性與一致性、擴展性、延遲的取舍沖突并不劇烈。通過合理的放棄一些性能與一致性,集群可以容忍多達 up to 的節(jié)點失效。這種折中在兩階段提交與 paxos 協(xié)議的區(qū)別里體現(xià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é)調者可以解決這個問題,但是去中心化的數(shù)據(jù)庫能夠提供更好的容錯性。去中心化的主要做法是利用精心設計的傳染協(xié)議[7],這種協(xié)議相對簡單,但是提供了很好的收斂時間,而且能夠容忍任何節(jié)點的失效和網絡隔離。盡管有許多類型的傳染算法,我們只關注反熵協(xié)議,因為nosql數(shù)據(jù)庫都在使用它。

反熵協(xié)議假定同步會按照一個固定進度表執(zhí)行,每個節(jié)點定期隨機或是按照某種規(guī)則選擇另外一個節(jié)點交換數(shù)據(jù),消除差異。有三種反風格的反熵協(xié)議:推,拉和混合。推協(xié)議的原理是簡單選取一個隨機節(jié)點然后把數(shù)據(jù)狀態(tài)發(fā)送過去。在真實應用中將全部數(shù)據(jù)都推送出去顯然是愚蠢的,所以節(jié)點一般按照下圖所示的方式工作。

NoSQL數(shù)據(jù)庫的分布式算法詳解

節(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é)點發(fā)生聯(lián)系。

NoSQL數(shù)據(jù)庫的分布式算法詳解

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

盡管這些技術看起來很簡單,仍然有許多研究關注于不同約束條件下反熵協(xié)議的性能表現(xiàn)。其中之一通過一種更有效的結構使用網絡拓撲來取代隨機選取 [10] 。在網絡帶寬有限的條件下調整傳輸率或使用先進的規(guī)則來選取要同步的數(shù)據(jù) [9]。摘要計算也面臨挑戰(zhàn),數(shù)據(jù)庫會維護一份最近更新的日志以有助于摘要計算。

最終一致數(shù)據(jù)類型eventually consistent data types

在上一節(jié)我們假定兩個節(jié)點總是合并他們的數(shù)據(jù)版本。但要解決更新沖突并不容易,讓所有副本都最終達到一個語義上正確的值出乎意料的難。一個眾所周知的例子是amazon dynamo數(shù)據(jù)庫[8]中已經刪除的條目可以重現(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é)點維護一對計數(shù)器[1]:

1 class counter { 2 int[] plus 3 int[] minus 4 int node_id 5 6 increment() { 7 plus[node_id]++ 8 } 9 10 decrement() { 11 minus[node_id]++ 12 } 13 14 get() { 15 return sum(plus) – sum(minus) 16 } 17 18 merge(counter other) { 19 for i in 1..max_id { 20 plus[i] = max(plus[i], other.plus[i]) 21 minus[i] = max(minus[i], other.minus[i]) 22 } 23 } 24 }

cassandra用類似的方法計數(shù)[11]。利用基于狀態(tài)的或是基于操作的復制理論也可以設計出更復雜的最終一致的數(shù)據(jù)結構。例如,[1]中就提及了一系列這樣的數(shù)據(jù)結構,包括:

  • 計數(shù)器(加減操作)
  • 集合(添加和移除操作)
  • 圖(增加邊或頂點,移除邊或頂點)
  • 列表(插入某位置或者移除某位置)

最終一致數(shù)據(jù)類型的功能通常是有限的,還會帶來額外的性能開銷。

數(shù)據(jù)放置

這部分主要關注控制在分布式數(shù)據(jù)庫中放置數(shù)據(jù)的算法。這些算法負責把數(shù)據(jù)項映射到合適的物理節(jié)點上,在節(jié)點間遷移數(shù)據(jù)以及像內存這樣的資源的全局調配。

均衡數(shù)據(jù)

我們還是從一個簡單的協(xié)議開始,它可以提供集群節(jié)點間無縫的數(shù)據(jù)遷移。這常發(fā)生于像集群擴容(加入新節(jié)點),故障轉移(一些節(jié)點宕機)或是均衡數(shù)據(jù)(數(shù)據(jù)在節(jié)點間的分布不均衡)這樣的場景。如下圖a中所描繪的場景 – 有三個節(jié)點,數(shù)據(jù)隨便分布在三個節(jié)點上(假設數(shù)據(jù)都是key-value型)。

NoSQL數(shù)據(jù)庫的分布式算法詳解

如果數(shù)據(jù)庫不支持數(shù)據(jù)內部均衡,就要在每個節(jié)點上發(fā)布數(shù)據(jù)庫實例,如上面圖b所示。這需要手動進行集群擴展,停掉要遷移的數(shù)據(jù)庫實例,把它轉移到新節(jié)點上,再在新節(jié)點上啟動,如圖c所示。盡管數(shù)據(jù)庫能夠監(jiān)控到每一條記錄,包括mongodb, oracle coherence, 和還在開發(fā)中的 redis cluster 在內的許多系統(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)機。

NoSQL數(shù)據(jù)庫的分布式算法詳解

假定每個節(jié)點都知道集群拓撲,能夠把任意key映射到相應的數(shù)據(jù)分片,把數(shù)據(jù)分片映射到節(jié)點。如果節(jié)點判斷被請求的key屬于本地分片,就會在本地查找(上圖中上面的方框)。假如節(jié)點判斷請求的key屬于另一個節(jié)點x,他會發(fā)送一個永久重定向命令給客戶端(上圖中下方的方框)。永久重定向意味著客戶端可以緩存分片和節(jié)點間的映射關系。如果分片遷移正在進行,遷出節(jié)點和遷入節(jié)點會標記相應的分片并且將分片的數(shù)據(jù)加鎖逐條加鎖然后開始移動。遷出節(jié)點首先會在本地查找key,如果沒有找到,重定向客戶端到遷入節(jié)點,假如key已經遷移完畢的話。這種重定向是一次性的,并且不能被緩存。遷入節(jié)點在本地處理重定向,但定期查詢在遷移還沒完成前被永久重定向。

動態(tài)環(huán)境中的數(shù)據(jù)分片和復制

我們關注的另一個問題是怎么把記錄映射到物理節(jié)點。比較直接的方法是用一張表來記錄每個范圍的key與節(jié)點的映射關系,一個范圍的key對應到一個節(jié)點,或者用key的hash值與節(jié)點數(shù)取模得到的值作為節(jié)點id。但是hash取模的方法在集群發(fā)生更改的情況下就不是很好用,因為增加或者減少節(jié)點都會引起集群內的數(shù)據(jù)徹底重排。導致很難進行復制和故障恢復。

有許多方法在復制和故障恢復的角度進行了增強。最著名的就是一致性hash。網上已經有很多關于一致性hash的介紹了,所以在這里我只提供一個基本介紹,僅僅為了文章內容的完整性。下圖描繪了一致性hash的基本原理:

NoSQL數(shù)據(jù)庫的分布式算法詳解

一致性hash從根本上來講是一個鍵值映射結構 – 它把鍵(通常是hash過的)映射到物理節(jié)點。鍵經過hash之后的取值空間是一個有序的定長二進制字符串,很顯然每個在此范圍內的鍵都會被映射到圖a中 a、b、c三個節(jié)點中的某一個。為了副本復制,將取值空間閉合成一個環(huán),沿環(huán)順時針前行直到所有副本都被映射到合適的節(jié)點上,如圖b所示。換句話說,y將被定位在節(jié)點b上,因為它在b的范圍內,第一個副本應該放置在c,第二個副本放置在a,以此類推。

這種結構的好處體現(xiàn)在增加或減少一個節(jié)點的時候,因為它只會引起臨接區(qū)域的數(shù)據(jù)重新均衡。如圖c所示,節(jié)點d的加入只會對數(shù)據(jù)項x產生影響而對y無影響。同樣,移除節(jié)點b(或者b失效)只會影響y和x的副本,而不會對x自身造成影響。但是,正如參考資料[8]中所提到的,這種做法在帶來好處的同時也有弱點,那就是重新均衡的負擔都由鄰節(jié)點承受了,它們將移動大量的數(shù)據(jù)。通過將每個節(jié)點映射到多個范圍而不是一個范圍可以一定程度上減輕這個問題帶來的不利影響,如圖d所示。這是一個折中,它避免了重新均衡數(shù)據(jù)時負載過于集中,但是與基于模塊的映射相比,保持了總均衡數(shù)量適當降低。

給大規(guī)模的集群維護一個完整連貫的hash環(huán)很不容易。對于相對小一點的數(shù)據(jù)庫集群就不會有問題,研究如何在對等網絡中將數(shù)據(jù)放置與網絡路由結合起來很有意思。一個比較好的例子是chord算法,它使環(huán)的完整性讓步于單個節(jié)點的查找效率。chord算法也使用了環(huán)映射鍵到節(jié)點的理念,在這方面和一致性hash很相似。不同的是,一個特定節(jié)點維護一個短列表,列表中的節(jié)點在環(huán)上的邏輯位置是指數(shù)增長的(如下圖)。這使得可以使用二分搜索只需要幾次網絡跳躍就可以定位一個鍵。

NoSQL數(shù)據(jù)庫的分布式算法詳解

這張圖畫的是一個由16個節(jié)點組成的集群,描繪了節(jié)點a是如何查找放在節(jié)點d上的key的。 (a) 描繪了路由,(b) 描繪了環(huán)針對節(jié)點a、b、c的局部圖像。在參考資料[15]中有更多關于分散式系統(tǒng)中的數(shù)據(jù)復制的內容。

按照多個屬性的數(shù)據(jù)分片

當只需要通過主鍵來訪問數(shù)據(jù)的時候,一致性hash的數(shù)據(jù)放置策略很有效,但是當需要按照多個屬性來查詢的時候事情就會復雜得多。一種簡單的做法(mongodb使用的)是用主鍵來分布數(shù)據(jù)而不考慮其他屬性。這樣做的結果是依據(jù)主鍵的查詢可以被路由到接個合適的節(jié)點上,但是對其他查詢的處理就要遍歷集群的所有節(jié)點。查詢效率的不均衡造成下面的問題:

有一個數(shù)據(jù)集,其中的每條數(shù)據(jù)都有若干屬性和相應的值。是否有一種數(shù)據(jù)分布策略能夠使得限定了任意多個屬性的查詢會被交予盡量少的幾個節(jié)點執(zhí)行?

hyperdex數(shù)據(jù)庫提供了一種解決方案。基本思想是把每個屬性視作多維空間中的一個軸,將空間中的區(qū)域映射到物理節(jié)點上。一次查詢會被對應到一個由空間中多個相鄰區(qū)域組成的超平面,所以只有這些區(qū)域與該查詢有關。讓我們看看參考資料[6]中的一個例子:

NoSQL數(shù)據(jù)庫的分布式算法詳解

每一條數(shù)據(jù)都是一條用戶信息,有三個屬性first name 、last name 和phone number。這些屬性被視作一個三維空間,可行的數(shù)據(jù)分布策略是將每個象限映射到一個物理節(jié)點。像“first name = john”這樣的查詢對應到一個貫穿4個象限的平面,也即只有4個節(jié)點會參與處理此次查詢。有兩個屬性限制的查詢對應于一條貫穿兩個象限的直線,如上圖所示,因此只有2個節(jié)點會參與處理。

這個方法的問題是空間象限會呈屬性數(shù)的指數(shù)函數(shù)增長。結果就會是,只有幾個屬性限制的查詢會投射到許多個空間區(qū)域,也即許多臺服務器。將一個屬性較多的數(shù)據(jù)項拆分成幾個屬性相對較少的子項,并將每個子項都映射到一個獨立的子空間,而不是將整條數(shù)據(jù)映射到一個多維空間,這樣可以一定程度上緩解這個問題:

NoSQL數(shù)據(jù)庫的分布式算法詳解

這樣能夠提供更好的查詢到節(jié)點的映射,但是增加了集群協(xié)調的復雜度,因為這種情況下一條數(shù)據(jù)會散布在多個獨立的子空間,而每個子空間都對應各自的若干個物理節(jié)點,數(shù)據(jù)更新時就必須考慮事務問題。參考資料 [6]有這種技術的更多介紹和實現(xiàn)細節(jié)。

鈍化副本

有的應用有很強的隨機讀取要求,這就需要把所有數(shù)據(jù)放在內存里。在這種情況下,將數(shù)據(jù)分片并把每個分片主從復制通常需要兩倍以上的內存,因為每個數(shù)據(jù)都要在主節(jié)點和從節(jié)點上各有一份。為了在主節(jié)點失效的時候起到代替作用,從節(jié)點上的內存大小應該和主節(jié)點一樣。如果系統(tǒng)能夠容忍節(jié)點失效的時候出現(xiàn)短暫中斷或性能下降,也可以不要分片。

下面的圖描繪了4個節(jié)點上的16個分片,每個分片都有一份在內存里,副本存在硬盤上:

NoSQL數(shù)據(jù)庫的分布式算法詳解

灰色箭頭突出了節(jié)點2上的分片復制。其他節(jié)點上的分片也是同樣復制的。紅色箭頭描繪了在節(jié)點2失效的情況下副本怎樣加載進內存。集群內副本的均勻分布使得只需要預留很少的內存就可以存放節(jié)點失效情況下激活的副本。在上面的圖里,集群只預留了1/3的內存就可以承受單個節(jié)點的失效。特別要指出的是副本的激活(從硬盤加載入內存)會花費一些時間,這會造成短時間的性能下降或者正在恢復中的那部分數(shù)據(jù)服務中斷。

系統(tǒng)協(xié)調

在這部分我們將討論與系統(tǒng)協(xié)調相關的兩種技術。分布式協(xié)調是一個比較大的領域,數(shù)十年以來有很多人對此進行了深入的研究。這篇文章里只涉及兩種已經投入實用的技術。關于分布式鎖,consensus協(xié)議以及其他一些基礎技術的內容可以在很多書或者網絡資源中找到,也可以去看參考資料[17, 18, 21]。

故障檢測

故障檢測是任何一個擁有容錯性的分布式系統(tǒng)的基本功能。實際上所有的故障檢測協(xié)議都基于心跳通訊機制,原理很簡單,被監(jiān)控的組件定期發(fā)送心跳信息給監(jiān)控進程(或者由監(jiān)控進程輪詢被監(jiān)控組件),如果有一段時間沒有收到心跳信息就被認為失效了。除此之外,真正的分布式系統(tǒng)還要有另外一些功能要求:

自適應。故障檢測應該能夠應對暫時的網絡故障和延遲,以及集群拓撲、負載和帶寬的變化。但這有很大難度,因為沒有辦法去分辨一個長時間沒有響應的進程到底是不是真的失效了,因此,故障檢測需要權衡故障識別時間(花多長時間才能識別一個真正的故障,也即一個進程失去響應多久之后會被認為是失效)和虛假警報率之間的輕重。這個權衡因子應該能夠動態(tài)自動調整。

靈活性。乍看上去,故障檢測只需要輸出一個表明被監(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é)點已經失效,并釋放所有相關資源。

可擴展性和健壯性。失敗檢測作為一個系統(tǒng)功能應該能夠隨著系統(tǒng)的擴大而擴展。他應該是健壯和一致的,也即,即使在發(fā)生通訊故障的情況下,系統(tǒng)中的所有節(jié)點都應該有一個一致的看法(即所有節(jié)點都應該知道哪些節(jié)點是不可用的,那些節(jié)點是可用的,各節(jié)點對此的認知不能發(fā)生沖突,不能出現(xiàn)一部分節(jié)點知道某節(jié)點a不可用,而另一部分節(jié)點不知道的情況)

所謂的累計失效檢測器[12]可以解決前兩個問題,cassandra[16]對它進行了一些修改并應用在產品中。其基本工作流程如下:

對于每一個被監(jiān)控資源,檢測器記錄心跳信息到達時間ti。

計算在統(tǒng)計預測范圍內的到達時間的均值和方差。

假定到達時間的分布已知(下圖包括一個正態(tài)分布的公式),我們可以計算心跳延遲(當前時間t_now和上一次到達時間tc之間的差值) 的概率,用這個概率來判斷是否發(fā)生故障。如參考資料[12]中所建議的,可以使用對數(shù)函數(shù)來調整它以提高可用性。在這種情況下,輸出1意味著判斷錯誤(認為節(jié)點失效)的概率是10%,2意味著1%,以此類推。

NoSQL數(shù)據(jù)庫的分布式算法詳解

根據(jù)重要程度不同來分層次組織監(jiān)控區(qū),各區(qū)域之間通過謠言傳播協(xié)議或者中央容錯庫同步,這樣可以滿足擴展性的要求,又可以防止心跳信息在網絡中泛濫[14]。如下圖所示(6個故障檢測器組成了兩個區(qū)域,互相之間通過謠言傳播協(xié)議或者像zookeeper這樣的健壯性庫來聯(lián)系):

NoSQL數(shù)據(jù)庫的分布式算法詳解

協(xié)調者競選

協(xié)調者競選是用于強一致性數(shù)據(jù)庫的一個重要技術。首先,它可以組織主從結構的系統(tǒng)中主節(jié)點的故障恢復。其次,在網絡隔離的情況下,它可以斷開處于少數(shù)的那部分節(jié)點,以避免寫沖突。

bully 算法是一種相對簡單的協(xié)調者競選算法。mongodb 用了這個算法來決定副本集中主要的那一個。bully 算法的主要思想是集群的每個成員都可以聲明它是協(xié)調者并通知其他節(jié)點。別的節(jié)點可以選擇接受這個聲稱或是拒絕并進入協(xié)調者競爭。被其他所有節(jié)點接受的節(jié)點才能成為協(xié)調者。節(jié)點按照一些屬性來判斷誰應該勝出。這個屬性可以是一個靜態(tài)id,也可以是更新的度量像最近一次事務id(最新的節(jié)點會勝出)。

下圖的例子展示了bully算法的執(zhí)行過程。使用靜態(tài)id作為度量,id值更大的節(jié)點會勝出:

1、最初集群有5個節(jié)點,節(jié)點5是一個公認的協(xié)調者。
2、假設節(jié)點5掛了,并且節(jié)點2和節(jié)點3同時發(fā)現(xiàn)了這一情況。兩個節(jié)點開始競選并發(fā)送競選消息給id更大的節(jié)點。
3、節(jié)點4淘汰了節(jié)點2和3,節(jié)點3淘汰了節(jié)點2。
4、這時候節(jié)點1察覺了節(jié)點5失效并向所有id更大的節(jié)點發(fā)送了競選信息。
5、節(jié)點2、3和4都淘汰了節(jié)點1。
6、節(jié)點4發(fā)送競選信息給節(jié)點5。
7、節(jié)點5沒有響應,所以節(jié)點4宣布自己當選并向其他節(jié)點通告了這一消息。

NoSQL數(shù)據(jù)庫的分布式算法詳解

協(xié)調者競選過程會統(tǒng)計參與的節(jié)點數(shù)目并確保集群中至少一半的節(jié)點參與了競選。這確保了在網絡隔離的情況下只有一部分節(jié)點能選出協(xié)調者(假設網絡中網絡會被分割成多塊區(qū)域,之間互不聯(lián)通,協(xié)調者競選的結果必然會在節(jié)點數(shù)相對比較多的那個區(qū)域中選出協(xié)調者,當然前提是那個區(qū)域中的可用節(jié)點多于集群原有節(jié)點數(shù)的半數(shù)。如果集群被隔離成幾個區(qū)塊,而沒有一個區(qū)塊的節(jié)點數(shù)多于原有節(jié)點總數(shù)的一半,那就無法選舉出協(xié)調者,當然這樣的情況下也別指望集群能夠繼續(xù)提供服務了)。

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 爱色av网站| 中文字幕免费观看 | 亚洲国产精品yw在线观看 | 最新中文字幕在线 | 国产毛片av| 成人h动漫精品一区二区器材 | 成年人免费观看网站 | 欧美激情一区二区三级高清视频 | 久久久久久久免费 | 伊人色网| 亚洲电影一区二区三区 | 免费黄看片 | 亚洲不卡| 日韩欧美在线观看 | 天天操天天碰 | 在线国产视频 | 欧美一区二区三区精品 | 亚洲国产精品久久久久久 | 免费网站在线 | 国产精品美女www爽爽爽软件 | 奇米成人 | av黄网| 欧美成人久久久免费播放 | 免费一二三区 | 亚洲精品久久久久久久久久久 | 国产成人在线视频 | 亚洲成av人片一区二区梦乃 | a级在线 | 免费一级毛片 | 毛片免费观看视频 | 国产三级在线观看 | 亚洲在线一区 | 偷偷干夜夜拍 | 久久国产成人 | 精精国产| 永久免费av | 国产精品久久久久久久浪潮网站 | 日韩精品99 | 欧美一级网站 | 午夜在线视频 | 免费国产wwwwwww网站 |