福哥答案2021-01-31:
[答案來自此連結:](https://www.zhihu.com/question/442112697)
一個叢集模式的官方推薦最小最佳實踐方案是 6 個節點,3 個 Master 3 個 Slave 的模式。
Redis 將鍵空間分為了 16384 個槽,透過以下演算法確定每一個 key 的槽:
CRC16(key) mod 16384
由於 16384 = 2 的 14 次方,對一個 2 的 n 次方取餘相當於對於它的 2 的 n 次方減一取與運算。所以最佳化為:
CRC16(key) & 16383
當 key 包含 hash tags 的時候(例如 key{sub}1),會以 sub tags 中指定的字串(就是 sub )計算槽,所以key{sub}1和key{sub}2會到同一個槽中。
客戶端可以傳送讀取任一個槽的命令到任一個叢集例項,當槽屬於請求的例項的時候,就會處理,否則會告訴客戶端這個槽在哪裡,例如如果將下面命令發到第二個 Master:
GET key1
返回: MOVED slot ip:port(第一個Master的)
預設情況下,所有的讀寫命令只能傳送到 Master。如果需要使用 Slave 處理讀請求,需要先在客戶端執行 readonly 命令。
主從自動切換機制
當一個 Master 發生故障,如果有 Slave,則會切換為 Master。
如何判斷 Master 發生故障了呢?Redis 叢集配置中有一個配置,cluster-node-timeout叢集心跳超時時間。當叢集內節點建立連線後,定時任務 clusterCron 函式(參考原始碼:https://github.com/redis/redis/blob/6.0/src/cluster.c)會每隔一秒隨機選擇一個節點發送心跳。如果在超時時間(cluster-node-timeout)的時間內未收到心跳響應,則將這個節點標記為 pfail。如果叢集中有一半以上的 Master 標記一個節點的狀態是 pfail,那麼這個節點的狀態就會變成 fail。
當節點變成 fail 就會觸發自動主從切換。主從切換的過程,也涉及到類似的選舉:
1.當某個 Master 被標記為 fail 之後,對應的 Slave 節點執行定時任務 clusterCron 函式時,選取複製偏移量,也就是主從同步進度最大、資料最新的 Slave 嘗試變為主。
2.這個 Slave 設定自己的 currentEpoch += 1(正常情況下叢集中所有的 currentEpoch 相同,每次選舉都會加 1,並且每個 currentEpoch 只能投一次,防止多個 Slave 同時發起選舉後難以獲取大多數票),之後向所有的 Master 傳送 failover 請求,如果得到大多數 Master 的同意則開始執行主從切換。
叢集不可用情況
根據上面的描述,我們可以總結出如下不可用的情況
1.當訪問一個 Master 和 Slave 節點都掛了的槽的時候,會報槽無法獲取。
2.當叢集 Master 節點個數小於 3 個的時候,或者叢集可用節點個數為偶數的時候,基於 fail 的這種選舉機制的自動主從切換過程可能會不能正常工作,一個是標記 fail 的過程,一個是選舉新的 master 的過程,都有可能異常。
***