將成員變更納入到演算法中是raft易於應用到實踐中的關鍵,相對於paxos,它給出了明確的變更過程(實踐的基礎,任何現實的系統中都會遇到因為硬體故障等原因引起的節點變更的操作)。
顯然,我們可以通過shutdown集群,然後變更配置後重啟集群的方式達到成員變更的目的。但是這種操作會損失系統的可用性,同時會帶來操作失誤引起的風險。支援自動化配置,即配置可以在集群執行期間進行動態的變更(不影響可用性)顯示是乙個非常重要的特性。
在成員變更時,因為無法做到在同乙個時刻使所有的節點從舊配置轉換到新配置,那麼直接從就配置向新配置切換就可能存在乙個節點同時滿足新舊配置的「超過半數」原則。
如下圖,原集群由server1、server2、server3,現在對集群做變更,增加server4、server5。如果採用直接從舊配置到新配置的切換,那麼有一段時間存在兩個不想交的「超過半數的集群」。
上圖,中在中間位置server1可以通過自身和server2的選票成為leader(滿足舊配置下收到大多數選票的原則);server3可以通過自身和server4、server5的選票成為leader(滿足新配置線,即集群有5個節點的情況下的收到大多數選票的原則);此時整個集群可能在同一任期**現了兩個leader,這和協議是違背的。
為了保證安全性,raft採用了一種兩階段的方式。
第一階段稱為joint consensus,當joint consensus被提交後切換到新的配置下。
joint consensus狀態下:
具體的切換過程如下:
從上圖可以看出,不存在乙個階段c-old和c-new可以同時根據自己的配置做出決定,所以不會出現本文開頭描述的情況。
如果當前的leader不在c-new的配置中會怎麼樣(即當前的leader是乙個要被下線的節點)?
在c-old-new的狀態下,leader依舊可用;在c-new被commit之後leader實際已經從集群中脫離,此時可以對leader節點進行下線操作,而新集群則會在c-new的配置下重新選舉出乙個leader。
如果在配置分發過程中leader crash了會怎麼樣?
這個問題要分為多種情況:1. c-new已經分發到超過半數節點、2. c-new還沒分發到超過半數的節點
情況1:c-new已經分發到超過半數節點
集群開始重新選舉,此時在c-new的規則下,舊節點(不存在新配置中的節點)不會贏得選舉(因為他們要在c-old-new的情況下決定,但是拿不到c-new的選票),只有拿到c-new的節點可能成為leader並繼續下發c-new配置,流程恢復。
情況2:c-new還沒分發到超過半數的節點
這種情況下,c-old-new和c-new的節點都可以成為leader,但是無所謂,因為無論誰成為leader,都能根據當前的配置繼續完成後續流程(如果是c-new那麼相當與完成了最終的配置,不在c-new的節點會因為沒有心跳資料而失效)
舊節點下線造成的問題:舊節點收不到心跳觸發選舉,傳送請求給c-old-new中的節點,是否會影響集群正常執行
raft的處理方式:當節點確信有leader存在時,不會進行投票(在leader超時之前收到新的投票請求時不會提公升term和投票)。且開始選舉之前等待乙個選舉超時時間,這樣在新leader正常工作的情況下,不會受到舊節點的影響。
舊節點在發起選舉前需要等待一段時間,那麼這段時間新leader可以傳送心跳,這樣就減少了影響。 對正常流程的影響不大。(leader失效後要等一段時間,沒有及時觸發,然而本身這裡就有乙個判斷失效的時間,好像影響不大;比如原先超時時間是10s,那麼如果設定成5s,原策略下10s超時就是10s後開始選舉,新策略下5s超時就是超時後再等5s再開始選舉,影響就是超時時間變短)
新的伺服器沒有任何資料,加入進來進來怎麼保證系統的可用性(這個時候新日誌沒辦法commit就沒辦法響應給客戶端)?
新加入的節點需要時間複製資料,在這個過程完成之前,raft採用以下機制來保證可用性: 新加入節點沒有投票權(leader複製日誌給他們,但是不將他們考慮在機器數量裡面——即在判斷是否超過半數時不把這些節點考慮在內),直到這些節點的日誌追上其他節點。
**:翻譯:
動畫演示:
42 成員物件
成員物件就是類的成員是物件型別,在類當中定義物件。例1 在類內定義中將另乙個類的物件作為成員 在類內定義中將另乙個類的物件作為成員 include class a class b void main 結果輸出為 10。例2 在類內定義乙個指向其他類物件例項的指標 在類內定義乙個指向其他類物件例項的指...
條款24 成員函式查詢
成員函式的查詢過程要涉及到三個步驟。首先,編譯器查詢函式的名字,然後從後續的函式選擇乙個最匹配的函式,最後,編譯器檢查函式的訪問許可權。大多數與函式名不匹配的錯誤並不是編譯器本身的問題,而是我們對成員函式查詢機制的理解有問題。考慮下面的 class b class d public b d d d....
15 成員函式的分離
1 標頭檔案的宣告 pragma once 表示的是只包含一次 ifndef a h意思是 if not define a.h 如果不存在a.h 接著的語句應該 define a h 就引入a.h 最後一句應該寫 endif 否則不需要引入 ifndef teacher2 h define teac...