1. 程式人生 > 實用技巧 >分散式系統理論之Quorum機制

分散式系統理論之Quorum機制

分散式系統理論之Quorum機制

一,Quorum機制介紹

在分散式系統中有個CAP理論,對於P(分割槽容忍性)而言,是實際存在 從而無法避免的。因為,分佈系統中的處理不是在本機,而是網路中的許多機器相互通訊,故網路分割槽、網路通訊故障問題無法避免。因此,只能儘量地在C 和 A 之間尋求平衡。對於資料儲存而言,為了提高可用性(Availability),採用了副本備份,比如對於HDFS,預設每塊資料存三份。某資料塊所在的機器宕機了,就去該資料塊副本所在的機器上讀取(從這可以看出,資料分佈方式是按“資料塊”為單位分佈的)

但是,問題來了,當需要修改資料時,就需要更新所有的副本資料,這樣才能保證資料的一致性(Consistency)。因此,就需要在 C(Consistency) 和 A(Availability) 之間權衡。

而Quorum機制,就是這樣的一種權衡機制,一種將“讀寫轉化”的模型。在介紹Quorum之前,先看一個極端的情況:WARO機制

WARO(Write All Read one)是一種簡單的副本控制協議,當Client請求向某副本寫資料時(更新資料),只有當所有的副本都更新成功之後,這次寫操作才算成功,否則視為失敗。

從這裡可以看出兩點:①寫操作很脆弱,因為只要有一個副本更新失敗,此次寫操作就視為失敗了。②讀操作很簡單,因為,所有的副本更新成功,才視為更新成功,從而保證所有的副本一致。這樣,只需要讀任何一個副本上的資料即可。假設有N個副本,N-1個都宕機了,剩下的那個副本仍能提供讀服務;但是隻要有一個副本宕機了,寫服務就不會成功。

WARO犧牲了更新服務的可用性,最大程度地增強了讀服務的可用性。而Quorum就是更新服務和讀服務之間進行一個折衷。

Quorum機制是“抽屜原理”的一個應用。定義如下:假設有N個副本,更新操作wi在W個副本中更新成功之後,才認為此次更新操作wi成功。稱成功提交的更新操作對應的資料為:“成功提交的資料”。對於讀操作而言,至少需要讀R個副本才能讀到此次更新的資料。其中,W+R>N ,即W和R有重疊。一般,W+R=N+1

假設系統中有5個副本,W=3,R=3。初始時資料為(V1,V1,V1,V1,V1)--成功提交的版本號為1

當某次更新操作在3個副本上成功後,就認為此次更新操作成功。資料變成:(V2,V2,V2,V1,V1)--成功提交後,版本號變成2

因此,最多隻需要讀3個副本,一定能夠讀到V2(此次更新成功的資料)。而在後臺,可對剩餘的V1同步到V2,而不需要讓Client知道。

二,Quorum機制分析

①Quorum機制無法保證強一致性

所謂強一致性就是:任何時刻任何使用者或節點都可以讀到最近一次成功提交的副本資料。強一致性是程度最高的一致性要求,也是實踐中最難以實現的一致性。

因為,僅僅通過Quorum機制無法確定最新已經成功提交的版本號。

比如,上面的V2成功提交後(已經寫入W=3份),儘管讀取3個副本時一定能讀到V2,如果剛好讀到的是(V2,V2,V2),則此次讀取的資料是最新成功提交的資料,因為W=3,而此時剛好讀到了3份V2。如果讀到的是(V2,V1,V1),則無法確定是一個成功提交的版本,還需要繼續再讀,直到讀到V2的達到3份為止,這時才能確定V2就是已經成功提交的最新的資料。

1)如何讀取最新的資料?---在已經知道最近成功提交的資料版本號的前提下,最多讀R個副本就可以讀到最新的資料了。

2)如何確定 最高版本號 的資料是一個成功提交的資料?---繼續讀其他的副本,直到讀到的 最高版本號副本 出現了W次。

②基於Quorum機制選擇 primary

中心節點(伺服器)讀取R個副本,選擇R個副本中版本號最高的副本作為新的primary。

新選出的primary不能立即提供服務,還需要與至少與W個副本完成同步後,才能提供服務---為了保證Quorum機制的規則:W+R>N

至於如何處理同步過程中衝突的資料,則需要視情況而定。

比如,(V2,V2,V1,V1,V1),R=3,如果讀取的3個副本是:(V1,V1,V1)則高版本的 V2需要丟棄。

如果讀取的3個副本是(V2,V1,V1),則低版本的V1需要同步到V2

三,Quorum機制應用例項

HDFS高可用性實現

HDFS的執行依賴於NameNode,如果NameNode掛了,那麼整個HDFS就用不了了,因此就存在單點故障(single point of failure);其次,如果需要升級或者維護停止NameNode,整個HDFS也用不了。為了解決這個問題,採用了QJM機制(Quorum Journal Manager)實現HDFS的HA(High Availability)。注意,一開始採用的“共享儲存”機制,關於共享儲存機制的不足,可參考:(還提到了QJM的優點)

In a typical HA cluster, two separate machines are configured as NameNodes.
At any point in time, exactly one of the NameNodes is in an Active state, and the other is in a Standby state. 
The Active NameNode is responsible for all client operations in the cluster, while the Standby is simply acting as a slave, 
maintaining enough state to provide a fast failover if necessary.

為了實現HA,需要兩臺NameNode機器,一臺是Active NameNode,負責Client請求。另一臺是StandBy NameNode,負責與Active NameNode同步資料,從而快速 failover。

那麼,這裡就有個問題,StandBy NameNode是如何同步Active NameNode上的資料的呢?主要同步是哪些資料呢?

資料同步就用到了Quorum機制。同步的資料 主要是EditLog

In order for the Standby node to keep its state synchronized with the Active node, 
both nodes communicate with a group of separate daemons called “JournalNodes” (JNs). 

資料同步用到了一個第三方”叢集“:Journal Nodes。Active NameNode 和 StandBy NameNode 都與JournalNodes通訊,從而實現同步。

''''''''''''''''''''''''''''''''''

每次 NameNode 寫 EditLog 的時候,除了向本地磁碟寫入 EditLog 之外,也會並行地向 JournalNode 叢集之中的每一個 JournalNode 傳送寫請求,只要大多數 (majority) 的 JournalNode 節點返回成功就認為向 JournalNode 叢集寫入 EditLog 成功。如果有 2N+1 臺 JournalNode,那麼根據大多數的原則,最多可以容忍有 N 臺 JournalNode 節點掛掉。

這就是:Quorum機制。每次寫入JournalNode的機器數目達到大多數(W)時,就認為本次寫操作成功了。

'''''''''''''''''''''''''''''''''

這樣,每次對Active NameNode中的元資料進行修改時,都會將該修改寫入JournalNode叢集的大多數機器中,才認為此次修改成功。

當Active NameNode宕機時,StandBy NameNode 向JournalNode同步EditLog,從而保證了HA。

Active NameNode 向 JournalNode 叢集提交 EditLog 是同步的
但 Standby NameNode 採用的是定時從 JournalNode 叢集上同步 EditLog 的方式,那麼 Standby NameNode 記憶體中檔案系統映象有很大的可能是落後於 Active NameNode 的,
所以 Standby NameNode 在轉換為 Active NameNode 的時候需要把落後的 EditLog 補上來。

具體的同步過程可參考:Hadoop NameNode 高可用 (High Availability) 實現解析

In order to provide a fast failover, it is also necessary that the Standby node have up-to-date information
regarding the location of blocks in the cluster. In order to achieve this, the DataNodes are configured with the location of both NameNodes, 
and send block location information and heartbeats to both.

此外,為了實現快速failover,StandBy NameNode 需要實時地與各個DataNode通訊以獲得每個資料塊的地址資訊。為咐要這樣?

因為:每個資料塊的地址資訊不屬於“元資訊”,並沒有儲存在 FsImage、CheckPoint...,這是因為地址資訊變化比較大。比如說,一臺DataNode下線了,其上面的資料塊地址資訊就全無效了,而且為了達到指定的資料塊“複製因子”,還需要在其他機器上覆制該資料塊。

而快速failover,是指Active NameNode宕機後,StandBy NameNode立即就能提供服務。因此,DataNode也需要實時向 StandBy NameNode 傳送 block report

另外,還有手動failover 和 自動 failover,自動failover需要Zookeeper的支援,具體可參考官網:HDFS High Availability Using the Quorum Journal Manager

如何避免“Split Brain”(腦裂)問題?

Split Brain 是指在同一時刻有兩個認為自己處於 Active 狀態的 NameNode。

when a NameNode sends any message (or remote procedure call) to a JournalNode, it includes its epoch number as part of the request. 
Whenever the JournalNode receives such a message, it compares the epoch number against a locally stored value called the promised epoch. 
If the request is coming from a newer epoch, then it records that new epoch as its promised epoch.
 If instead the request is coming from an older epoch, then it rejects the request. This simple policy avoids split-brain

簡單地理解如下:每個NameNode 與 JournalNodes通訊時,需要帶一個 epoch numbers(epoch numbers 是唯一的且只增不減)。而每個JournalNode 都有一個本地的promised epoch。擁有值大的epoch numbers 的NameNode會使得JournalNode提升自己的 promised epoch,從而佔大多數,而epoch numbers較小的那個NameNode就成了少數派(Paxos協議思想)。

從而epoch number值大的NameNode才是真正的Active NameNode,擁有寫JournalNode的許可權。注意:(任何時刻只允許一個NameNode擁有寫JournalNode許可權)

when using the Quorum Journal Manager, only one NameNode will ever be allowed to write to the JournalNodes,
so there is no potential for corrupting the file system metadata from a split-brain scenario.

具體實現可參考:(還提到了QJM的優點)

四,參考資料

維基百科Quorum

https://issues.apache.org/jira/secure/attachment/12547598/qjournal-design.pdf

Hadoop2.6.0學習筆記(九)SPOF解決方案Quorum機制

HDFS HA與QJM[官網整理]

原文地址:http://www.cnblogs.com/hapjin/p/5626889.html