redis cluster原始碼研究--failover
failover是redis cluster的容錯機制,是redis cluster最核心功能之一;它允許在某些節點失效情況下,叢集還能正常提供服務。
redis cluster採用主從架構,任何時候只有主節點提供服務,從節點進行熱備份,故其容錯機制是主從切換機制,即主節點失效後,選取一個從節點作為新的主節點。在實現上也複用了舊版本的主從同步機制。
從縱向看,redis cluster是一層架構,節點分為主節點和從節點。從節點掛掉或失效,不需要進行failover,redis cluster能正常提供服務;主節點掛掉或失效需要進行failover。另外,redis cluster還支援manual failover,即人工進行failover,將從節點變為主節點,即使主節點還活著。下面將介紹這兩種型別的failover。
一、主節點失效產生的failover
1、(主)節點失效檢測
一般地,叢集中的節點會向其他節點發送PING資料包,同時也總是應答(accept)來自叢集連線埠的連線請求,並對接收到的PING資料包進行回覆。
當一個節點向另一個節點發PING命令,但是目標節點未能在給定的時限(node timeout)內回覆時,那麼傳送命令的節點會將目標節點標記為PFAIL(possible failure)。
由於節點間的互動總是伴隨著資訊傳播的功能,此時每次當節點對其他節點發送 PING 命令的時候,就會告知目標節點此時叢集中已經被標記為PFAIL或者FAIL標記的節點。
相應的,當節點接收到其他節點發來的資訊時, 它會記下那些被其他節點標記為失效的節點。 這稱為失效報告(failure report)。
如果節點已經將某個節點標記為PFAIL,並且根據節點所收到的失效報告顯式,叢集中的大部分其他主節點(n/2+1)也認為那個節點進入了失效狀態,那麼節點會將那個PFAIL節點的狀態標記為FAIL。
一旦某個節點被標記為FAIL,關於這個節點已失效的資訊就會被廣播到整個叢集,所有接收到這條資訊的節點都會將失效節點標記為FAIL。
2、選舉主節點一旦某個主節點進入 FAIL 狀態, 叢集變為FAIL狀態,同時會觸發failover。failover的目的是從從節點中選舉出新的主節點,使得叢集恢復正常繼續提供服務。
整個主節點選舉的過程可分為申請、授權、升級、同步四個階段:
(1)申請
新的主節點由原已失效的主節點屬下的所有從節點中自行選舉產生,從節點的選舉遵循以下條件:
a、這個節點是已下線主節點的從節點;
b、已下線主節點負責處理的雜湊槽數量非空;
c、主從節點之間的複製連線的斷線時長有限,不超過 ( (node-timeout * slave-validity-factor) + repl-ping-slave-period )。
如果一個從節點滿足了以上的所有條件,那麼這個從節點將向叢集中的其他主節點發送授權請求,詢問它們是否允許自己升級為新的主節點。
從節點發送授權請求的時機會根據各從節點與主節點的資料偏差來進行排序,讓偏差小的從節點優先發起授權請求。
(2)授權
其他主節點會遵信以下三點標準來進行判斷:
a、 傳送授權請求的是從節點,而且它所屬的主節點處於FAIL狀態 ;
b、 從節點的currentEpoch〉自身的currentEpoch,從節點的configEpoch>=自身儲存的該從節點的configEpoch;
c、 這個從節點處於正常的執行狀態,沒有被標記為FAIL或PFAIL狀態;
如果傳送授權請求的從節點滿足以上標準,那麼主節點將同意從節點的升級要求,向從節點返回CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK授權。
(3)升級
一旦某個從節點在給定的時限內得到大部分主節點(n/2+1)的授權,它就會接管所有由已下線主節點負責處理的雜湊槽,並主動向其他節點發送一個PONG資料包,包含以下內容:
a、 告知其他節點自己現在是主節點了
b、 告知其他節點自己是一個ROMOTED SLAVE,即已升級的從節點;
c、告知其他節點都根據自己新的節點屬性資訊對配置進行相應的更新
(4)同步其他節點在接收到ROMOTED SLAVE的告知後,會根據新的主節點對配置進行相應的更新。特別地,其他從節點會將新的主節點設為自己的主節點,從而與新的主節
點進行資料同步。至此,failover結束,叢集恢復正常狀態。
此時,如果原主節點恢復正常,但由於其的configEpoch小於其他節點儲存的configEpoch(failover了產生較大的configEpoch),故其配置會被更新為最新配置,並將自己設新主節點的從節點。
另外,在failover過程中,如果原主節點恢復正常,failover中止,不會產生新的主節點。
二、Manual Failover
Manual Failover是一種運維功能,允許手動設定從節點為新的主節點,即使主節點還活著。
Manual Failover與上面介紹的Failover流程大都相同,除了下面兩點不同:
(1)觸發機制不同,Manual Failover是通過客戶端傳送cluster failover觸發,而且傳送物件只能是從節點;
(2)申請條件不同,Manual Failover不需要主節點失效,failover有效時長固定為5秒,而且只有收到命令的從節點才會發起申請。
另外,Manual Failover分force和非force,區別在於:非force需要等從節點完全同步完主節點的資料後才進行failover,保證不丟失資料,在這過程中,原主節點停止寫操作;而force不進行進行資料完整同步,直接進行failover。
三、叢集狀態檢測
叢集有OK和FAIL兩種狀態,可以通過CLUSTER INFO命令檢視。當叢集發生配置變化時, 叢集中的每個節點都會對它所知道的節點進行掃描,只要叢集中至少有一個雜湊槽不可用(即負責該雜湊槽的主節點失效),叢集就會進入FAIL狀態,停止處理任何命令。
另外,當大部分主節點都進入PFAIL狀態時,叢集也會進入FAIL狀態。這是因為要將一個節點從PFAIL狀態改變為FAIL狀態,必須要有大部分主節點(n/2+1)認可,當叢集中的大部分主節點都進入PFAIL時,單憑少數節點是沒有辦法將一個節點標記為FAIL狀態的。 然而叢集中的大部分主節點(n/2+1)進入了下線狀態,讓叢集變為FAIL,是為了防止少數存著主節點繼續處理使用者請求,這解決了出現網路分割槽時,一個可能被兩個主節點負責的雜湊槽,同時被使用者進行讀寫操作(通過禁掉其中少數派讀寫操作,證保只有一個讀寫操作),造成資料丟失資料問題。
說明:上面n/2+1的n是指叢集裡有負責雜湊槽的主節點個數。