本筆記是對Redis Cluster Spec - Configuration handling, propagation, and failovers的歸納總結。
Epoch
- 可以把Epoch當作是一個版本號,是一個64位無符號整形
- 每個Node自己有一份Cluster.currentEpoch、MySelf.configEpoch、其他Node.configEpoch,詳見文檔。
- 每個Master有自己的ConfigEpoch且在整個Cluster中唯一
- Slave的ConfigEpoch隨其Master
- Cluster.currentEpoch,該值等於所有Node中最大的ConfigEpoch的值
- Master的ConfigEpoch初始值是0,也就是說Cluster.CurrentEpoch的初始值也是0
- Node之間Gossip傳輸消息時,Receiver發現Sender的ConfigEpoch比自己大,那麼就更新自己的Cluster.CurrentEpoch爲該值,隨時間收斂,所有Node的Cluster.CurrentEpoch都變成一樣。
Slave Promotion
Slave的動作
下面是總結的在發生Slave Promotion時,Slave做的事情。
Master的動作
下面是總結的在發生Slave Promotion時,Master做的事情。
傳播Slots的配置
Slave贏得選舉之後會在己側更新Slots上的歸屬信息,然後在定時的PING/PONG中將這個信息傳播出去。
PING/PONG總是會攜帶上Slots所屬Master的信息(包括ConfigEpoch)
PING的Reciever如果發現Sender的某個Slot上的Master.ConfigEpoch比自己這裏記錄的小,那麼就會返回UPDATE
告訴Sender更新Slots歸屬信息。
下面是兩個規則:
- 如果一個Slot不屬於任何Master,然後有一個Master宣稱擁有它,那麼就修改己側的Slots信息把這個Slot關聯到這個Master上。
- 如果一個Slot已經歸屬一個Master,然後又有一個Master宣稱擁有它,那麼就看誰的ConfigEpoch大,大的那個贏
Node復活後遇到的問題
Node A有兩個Slot,然後它死了,它被頂替了,等它復活時發現兩個Slot一個被Node B接管,另一個被Node C接管了,那麼它:
- 因爲自己的ConfigEpoch已經很舊了,所以它復活後不負責任何Slot
- 然後它會成爲最後一個Slot的Master的Slave
Slave遷移算法
Slave遷移時一個自動過程。
舉個例子,現在有Master A、B,它們對應的Slave有A1、B1、B2。現在A死了,A1頂替上去,不過這個時候A1就是一個光棍Master(它沒有Slave),B有富餘的Slave(B1和B2),把其中一個勻給A1當Slave。
這個過程不需要共識,因爲只是修改Slave的歸屬,也不會修改ConfigEpoch。
Slave遷移有兩個規則:
- 當有多個Slave富餘時,選擇NodeID字典順最小的那個來遷移
- 只有當Master的Slave數量>=
cluster-migration-barrier
時,纔會挑選它的Slave做Migration
兩個跳過共識修改ConfigEpoch的操作
下面兩個操作比較危險,最好確定一個成功後再執行另一個:
-
CLUSTER_FAILOVER TAKEOVER
(手動Failover)直接將一個Slave提升爲Master,不需要大多數Master同意。 - Slot Migration同樣不需要大多數Master同意。
所以就有可能出現同一個Slot有兩個相同ConfigEpoch的Master宣稱由自己負責,這種衝突的解決算法是:
- 如果Master A發現Master B也宣稱了對Slot X的主權,並且兩者的ConfigEpoch一樣
- 如果Master A的NodeID的字典順比Master B的小
- 那麼Master A就把己側的CurrentEpoch+1,同時ConfigEpoch改成和CurrentEpoch一樣
Node重製
略,見文檔。
移除Node
略,見文檔。
一些自問自答
Q:ConfigEpoch何時變化?
A:Slave Promotion時、手動Failover時、Slot Migration時
Q:ConfigEpoch怎麼變化?
A:Node->ConfigEpoch = Cluster->CurrentEpoch + 1,結果也就是Cluster->CurrentEpoch加1了。源碼見這裏。
Q:兩個Master的ConfigEpoch一樣怎麼辦?
A:這個會出現在兩個Slave同時Promotion時,解決辦法是NodeID字典序比較小的那個會再一次Bump ConfigEpoch,源碼見這裏。
Q:ConfigEpoch有什麼用?
A:當有兩個Master宣稱自己擁有同一個/批Slot時,ConfigEpoch大的那個贏,因爲大的那個代表最新信息,其他Node只會採用贏的那方所宣稱的信息。
Q:CurrentEpoch有什麼用?
A:1)用來判定Node所獲得的Cluster信息的新舊。2)當Node要變更ConfigEpoch時派用處。
參考資料
官方文檔:
下面是餓了麼工程師寫的文章,比較透徹:
下面是兩篇阿里工程師的: