Oracle 法定人數簡介
Oracle 法定人數簡介增加了 2 個 ZooKeeper 執行個體叢集的可用性,並將故障偵測器稱為 Oracle。Oracle 的設計目的是授予權限給執行個體,該執行個體是 2 個執行個體組態中唯一剩下的執行個體,當其他執行個體被故障偵測器(Oracle)識別為有故障時。
Oracle 的實作
每個執行個體都應該存取一個檔案,其中包含 0 或 1,以指出此執行個體是否由 Oracle 授權。但是,此設計可以變更,因為故障偵測器演算法彼此不同。因此,可以在 QuorumOracleMaj 中覆寫 askOracle() 方法,以調整解碼 Oracle 訊息的首選方式。
部署內容
Oracle 的設計目的是增加 2 個 ZooKeeper 執行個體叢集的可用性;因此,投票成員的大小為 2。換句話說,Oracle 解決了在兩個執行個體組合中可能出現故障執行個體的共識問題。
如果投票成員的大小超過 2,讓 Oracle 正確運作的預期方式是在識別故障機器時重新組態叢集的大小。例如,在 5 個執行個體的組態中,當故障機器與 Leader 中斷連線時,預期會有一個 reconfig 重新組態客戶端要求給叢集,這會讓叢集重新形成為 4 個執行個體的組態。因此,一旦投票成員的大小等於 2,組態就會陷入 Oracle 設計用來解決的問題領域。
如何在 zoo.cfg 中部署 Oracle
無論叢集的大小為何,都必須在初始化時組態 oraclePath,這就像其他靜態參數一樣。以下顯示指定和啟用 Oracle 的正確方式。
oraclePath=/to/some/file
zoo.cfg 的範例
dataDir=/data
dataLogDir=/datalog
tickTime=2000
initLimit=5
syncLimit=2
autopurge.snapRetainCount=3
autopurge.purgeInterval=0
maxClientCnxns=60
standaloneEnabled=true
admin.enableServer=true
oraclePath=/chassis/mastership
server.1=0.0.0.0:2888:3888;2181
server.2=hw1:2888:3888;2181
QuorumOracleMaj 旨在讀取故障偵測器的結果,該結果寫在文字檔中,即 Oracle 檔案。
zoo.cfg 中的組態如下
oraclePath=/to/some/file
假設您將故障偵測器的結果寫在 /some/path/result.txt 中,則正確的組態如下
oraclePath=/some/path/result.txt
那麼,提供的檔案中正確的內容是什麼?可以使用下列指令從終端機建立範例檔案
$echo 1 > /some/path/result.txt
任何等效的檔案都適用於 QuorumOracleMaj 的目前實作。Oracle 檔案的數量應等於已組態為啟用 Oracle 的 ZooKeeper 執行個體數量。換句話說,每個 ZooKeeper 執行個體都應有其 Oracle 檔案,且檔案不得共用;否則,將會發生下一節中的問題。
啟用 Oracle 後有什麼不同
當讀取包含 oraclePath 的 zoo.cfg 時,QuorumPeerConfig 將建立 QuorumOracleMaj 執行個體,而非預設的 QuorumVerifier,QuorumMaj。QuorumOracleMaj 繼承自 QuorumMaj,且透過覆寫 containsQuorum() 方法與其超類別不同。QuorumOracleMaj 旨在在 Leader 失去所有追隨者且無法維持法定人數時執行其版本的 containsQuorum。在其他情況下,QuorumOracleMaj 將執行為 QuorumMaj。
我們應該注意 Oracle 的是什麼
我們考慮一個非同步分散式系統,其中包含 **2** 個 ZooKeeper 執行個體和一個 Oracle。
活性問題
當我們考慮 Oracle 滿足 [CT] 介紹的下列屬性時
Strong Completeness: There is a time after which every process that crashes is permanently suspected by every correct processes
系統的活性由 Oracle 確保。但是,當引入的 Oracle 無法維持此屬性時,預期會失去活性,如下例所示,
假設我們有一個 Leader 和一個追隨者,它們在廣播狀態中執行,當
- Leader 失敗,但 Oracle 未偵測到有問題的 Leader,這表示 Oracle 不會授權追隨者成為新的 Leader。
- 當追隨者失敗,但 Oracle 未偵測到有問題的追隨者,這表示 Oracle 將授權 Leader 推動系統前進。
安全問題
進度遺失
當系統中發生多重故障時,進度可能會遺失,如下例所示:
假設我們在廣播狀態下有一個 Leader(Ben)和一個 Follower(John),
At T1 with zxid(0x1_1): L-Ben fails, and the F-John takes over the system under the authorization from the Oracle.
At T2 with zxid(0x2_1): The F-John becomes a new Leader, L-John, and starts a new epoch.
At T3 with zxid(0x2_A): L-John fails
At T4 with zxid(0x2_A): Ben recovers up and starts its leader election.
At T5 with zxid(0x3_1): Ben becomes the new leader, L-Ben, under the authorization from the Oracle.
在這種情況下,系統在 L-Ben 故障後會遺失進度。
然而,可以透過讓 Oracle 能夠參考最新的 zxid 來防止進度遺失。當 Oracle 可以參考最新的 zxid 時,
At T5 with zxid(0x2_A): Ben will not end his leader election because the Oracle would not authorize although John is down.
儘管如此,我們還是以活性換取了安全性。
腦裂問題
我們認為 Oracle 滿足 [CT] 介紹的以下所需屬性,
Accuracy: There is a time after which some correct processes is never suspected by any processes
儘管如此,Oracle 給出的決策應當是互斥的。
換句話說,
假設我們在廣播狀態下有一個 Leader(Ben)和一個 Follower(John),
- 在任何時候,Oracle 都不能授權 Ben 和 John,即使故障偵測器認為彼此有故障。或者
- 在任何時候,對於任何兩個 Oracle 檔案中的任何兩個值,這些值都不會同時等於 1。
當 Oracle 在
- 系統啟動時
- 故障的執行個體從故障中復原時
無法在 Leader 選舉階段維護此屬性時,預計會發生腦裂。
故障偵測器實作概念範例
應該考慮故障偵測器的結果是授權查詢的 ZooKeeper 執行個體,在不等待故障偵測器識別的故障執行個體的情況下,是否有權讓系統向前推進。
硬體實作
假設兩個專用硬體 hw1 和 hw2 可以分別託管 ZooKeeper 執行個體 zk1 和 zk2,並形成一個叢集。一個硬體裝置連接到兩個硬體,並且能夠判斷硬體是否已開啟電源。因此,當 hw1 未開啟電源時,zk1 肯定有故障。因此,硬體裝置會將 hw2 上的 Oracle 檔案更新為 1,表示 zk1 有故障,並授權 zk2 讓系統向前推進。
軟體實作
使用 USB 裝置作為 Oracle 來維護進度
在 macOS 10.15.7 (19H2) 中,外部儲存裝置會掛載在 /Volumes
下。因此,我們可以插入包含所需資訊的 USB 裝置作為 Oracle。當裝置連接時,Oracle 會授權 Leader 推動系統前進,這也表示其他執行個體會失敗。有 六 個步驟可以重現此模擬。
- 首先,插入一個名為
Oracle
的 USB 裝置,然後我們可以預期/Volumes/Oracle
可以存取。 - 其次,我們在
/Volumes/Oracle
下建立一個包含1
的檔案,名為mastership
。現在我們可以存取/Volumes/Oracle/mastership
,而 zookeeper 執行個體也可以查看它是否有權限推動系統前進。檔案可以輕鬆透過以下指令產生$echo 1 > mastership
-
第三,你應該有一個類似以下範例的
zoo.cfg
dataDir=/data dataLogDir=/datalog tickTime=2000 initLimit=5 syncLimit=2 autopurge.snapRetainCount=3 autopurge.purgeInterval=0 maxClientCnxns=60 standaloneEnabled=true admin.enableServer=true oraclePath=/Volumes/Oracle/mastership server.1=0.0.0.0:2888:3888;2181 server.2=hw1:2888:3888;2181
(注意) 由於此模擬中只有一個 USB 裝置,因此不會發生腦裂問題。 此外,mastership
不應由多個執行個體共用。 因此,只有一個 ZooKeeper 執行個體會設定 Oracle。 更多資訊請參閱安全性問題區段。
- 第四,啟動叢集,預期它會正常形成法定人數。
- 第五,終止執行個體,不連接 USB 裝置或
mastership
包含 0。有兩個預期的場景
- 發生 Leader 故障,而剩餘的執行個體會因為 Oracle 而自行完成 Leader 選舉。
- 由於 Oracle,法定人數仍維持。
- 最後,當移除 USB 裝置時,
/Volumes/Oracle/mastership
會變得無法使用。因此,根據目前的實作,每當 Leader 查詢 Oracle 時,Oracle 會擲出例外並傳回FALSE
。重複第五步驟,然後預期系統無法從 Leader 故障中復原,或 Leader 會失去法定人數。無論哪種情況,服務都會中斷。
透過這些步驟,我們可以輕鬆展示和練習 Oracle 如何與兩個執行個體系統搭配使用。
參考文獻
[CT] Tushar Deepak Chandra 和 Sam Toueg。1991。非同步系統的不可靠故障偵測器(初稿)。在第十屆 ACM 分散式運算原理研討會論文集(PODC '91)。紐約、美國紐約州的計算機器協會,325-340。DOI:https://doi.org/10.1145/112600.112627