轉載:https://www.cnblogs.com/hapjin/p/5626889.html
https://www.iteye.com/news/32340
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借鑒了Paxos的思想,實現上更加簡潔,同樣解決了在多個節點並發寫入時的數據一致性問題。比如Amazon的Dynamo雲存儲系統中,就應用NWR來控制一致性。微信也有大量分布式存儲使用這個協議保證一致性。Quorum最初的思路來自“鴿巢原理”,同一份數據雖然在多個節點擁有多份副本,但是同一時刻這些副本只能用於讀或者只能用於寫。
- Quorum控制同一份數據不會同時讀寫,寫請求需要的副本數要求超過半數,寫操作時就沒有足夠的副本給讀操作;
- Quorum控制同一份數據的串行化修改,因為副本數要求,同一份數據不會被兩個寫請求同時修改。
Quorum又被稱為NWR協議:R表示讀取副本的數量;W表示寫入副本的數量;N表示總的節點數量。
- 假設N=2,R=1,W=1,R+W=N=2,在節點1寫入,節點2讀取,無法得到一致性的數據;
- 假設N=2,R=2,W=1,R+W>N,任意寫入某個節點,則必須同時讀取所有節點;
- 假設N=2,W=2,R=1,R+W>N,同時寫入所有節點,則讀取任意節點就可以得到結果。
要滿足一致性,必須滿足R+W>N。NWR值的不同組合有不同效果,當W+R>N時能實現強一致性。所以工程實現上需要N>=3,因為冗余數據是保證可靠性的手段,如果N=2,損失一個節點就退化為單節點。寫操作必須更新所有副本數據才能操作完成,對於寫頻繁的系統,少數節點被寫入的數據副本可以異步同步,但是只更新部分節點,讀取則需要訪問多個節點,讀寫總和超過總節點數才能保證讀到最新數據。可以根據請求類型調整BWR,需要可靠性則加大NR,需要平衡讀寫性能則調整RW。
微信有大量分布式存儲(QuorumKV)使用這個算法保證一致性,我們對這個算法做了改進,創造性地把數據副本分離出版本編號和數據存到不同設備,其中N=3(數據只有2份,版本編號有3份),在R=W=2時仍然可以保證強一致性。因為版本編號存放3份,對版本編號使用Quorum方式,通過版本編號協商,只有版本序號達成一致的情況下讀寫單機數據,從而在保證強一致性的同時實現高讀寫性能。實際數據只寫入一台數據節點,使用流水日志的方式進行同步,並更新版本編號。但是我們的分布式存儲(QuorumKV)仍存在數據可靠性比Paxos低的問題,因為數據只寫一份副本,依靠異步同步。如果數據節點故障,故障節點上沒有同步到另一個節點,數據將無法訪問。版本節點故障時,如果Quorum協議沒有設置W=3,也可能無法訪問正確的數據節點副本。
對於分布式存儲:
分布式存儲選用不同的一致性算法,和業務的具體情況相關。我們的分布式存儲在發展的不同階段,使用過不同的算法:業務的發展初期使用Quorum算法,成本壓力減少而業務穩定需求變大后,就開始使用Paxos算法。如果業務模型對數據一致性要求不高,使用Quorum則具有一定的成本和開發資源優勢。
