1 面試題
Redis集群模式的工作原理說一下?在集群模式下,key是如何尋址的?尋址都有哪些算法?了解一致性hash嗎?
2 考點分析
Redis不斷在發展-Redis cluster集群模式,可以做到在多台機器上,部署多個實例,每個實例存儲一部分的數據,同時每個實例可以帶上Redis從實例,自動確保說,如果Redis主實例掛了,會自動切換到redis從實例頂上來。
現在新版本,大家都是用Redis cluster的,也就是原生支持的集群模式,那么面試官肯定會就redis cluster對你來個幾連炮。要是你沒用過redis cluster,正常,以前很多人用codis之類的客戶端來支持集群,但是起碼你得研究一下redis cluster
3 Redis如何在保持讀寫分離+高可用的架構下,還能橫向擴容支撐1T+海量數據
-
redis單master架構的容量的瓶頸問題
- redis如何通過master橫向擴容支撐1T+數據量
3 數據分布算法:hash+一致性hash+redis cluster的hash slot
講解分布式數據存儲的核心算法,數據分布的算法
hash算法 -> 一致性hash算法(memcached) -> redis cluster,hash slot算法
用不同的算法,就決定了在多個master節點的時候,數據如何分布到這些節點上去,解決這個問題,這里向大家推薦一個java架構交流q裙:790047143
4 Redis cluster
- 自動將數據分片,每個master上放一部分數據
- 提供內置的高可用支持,部分master不可用時,還可繼續工作
在Redis cluster架構下,每個Redis要開放兩個端口,比如一個是6379,另外一個就是加10000的端口號,比如16379
16379端口用於節點間通信,也就是cluster bus集群總線
cluster bus的通信,用來故障檢測,配置更新,故障轉移授權
cluster bus用了另外一種二進制的協議 - gossip,主要用於節點間高效的數據交換,占用更少的網絡帶寬和處理時間
-
最老土的hash算法和弊端(大量緩存重建)
3、一致性hash算法(自動緩存遷移)+虛擬節點(自動負載均衡)
-
一致性hash算法的講解和優點
-
一致性hash算法的虛擬節點實現負載均衡
4、redis cluster的hash slot算法

redis cluster有固定的16384個hash slot,對每個key計算CRC16值,然后對16384取模,可以獲取key對應的hash slot
redis cluster中每個master都會持有部分slot,比如有3個master,那么可能每個master持有5000多個hash slot
hash slot讓node的增加和移除很簡單,增加一個master,就將其他master的hash slot移動部分過去,減少一個master,就將它的hash slot移動到其他master上去
移動hash slot的成本是非常低的
客戶端的api,可以對指定的數據,讓他們走同一個hash slot,通過hash tag來實現
5 節點間的內部通信機制
5.1 基礎通信原理
用於維護集群的元數據
5.1.1 集中式
- 集中式的集群元數據存儲和維護
- 優點
元數據的更新和讀取,時效性好,一旦元數據出現變更,立即更新到集中式的存儲中,其他節點讀取時立即就可感知 - 缺點
所有的元數據的跟新壓力全部集中在一個地方,可能會導致元數據的存儲有壓力
Redis cluster節點間采取的另一種稱為gossip的協議
互相之間不斷通信,保持整個集群所有節點的數據是完整的
gossip:好處在於,元數據的更新比較分散,不是集中在一個地方,更新請求會陸陸續續,打到所有節點上去更新,有一定的延時,降低了壓力; 缺點,元數據更新有延時,可能導致集群的一些操作會有一些滯后
我們剛才做reshard,去做另外一個操作,會發現說,configuration error,達成一致
(2)10000端口
每個節點都有一個專門用於節點間通信的端口,就是自己提供服務的端口號+10000,比如7001,那么用於節點間通信的就是17001端口
每隔節點每隔一段時間都會往另外幾個節點發送ping消息,同時其他幾點接收到ping之后返回pong
(3)交換的信息
故障信息,節點的增加和移除,hash slot信息,等等
5.1.2 gossip協議
-
gossip協議維護集群元數據
協議包含多種消息
meet
某節點發送meet給新加入的節點,讓新節點加入集群,然后新節點就會開始與其他節點通信
redis-trib.rb add-node
其實內部就是發送了一個gossip meet消息給新節點,通知該節點加入集群
ping
每個節點都會頻繁給其他節點發ping,其中包含自己的狀態還有自己維護的集群元數據,互相通過ping交換元數據
ping很頻繁,而且要攜帶一些元數據,可能會加重網絡的負擔
每個節點每s會執行10次ping,每次會選擇5個最久沒有通信的其他節點。當然如果發現某個節點通信延時達到了
cluster_node_timeout / 2
那么立即發送ping,避免數據交換延時過長,落后的時間太長了。比如說,兩節點之間已經10分鍾沒有交換數據,那么整個集群處於嚴重的元數據不一致的情況,就會有問題。所以 cluster_node_timeout
可以調節,如果調節比較大,那么會降低發送頻率
每次ping,一個是帶上自己節點的信息,還有就是帶上1/10其他節點的信息,發送出去,進行數據交換。至少包含3個其他節點的信息,最多包含總節點-2個其他節點的信息
pong
返回ping和meet,包含自己的狀態和其他信息,也可用於信息廣播和更新
fail
某個節點判斷另一個節點fail后,就發送fail給其他節點,通知其他節點,指定的節點宕機啦!
6 面向集群的Jedis內部實現原理
開發Jedis,Redis的Java客戶端
jedis cluster api與redis cluster集群交互的一些基本原理
6.1 基於重定向的客戶端
redis-cli -c,自動重定向
6.1.1 請求重定向
客戶端可能會挑選任意一個Redis實例去發送命令,每個實例接收到命令,都會計算key對應的hash slot
若在本地就在本地處理,否則返回moved給客戶端,讓客戶端重定向
cluster keyslot mykey
可查看一個key對應的hash slot是什么
用redis-cli的時候,可加入 -c
參數,支持自動的請求重定向,redis-cli接收到moved之后,會自動重定向到對應的節點執行命令
6.1.2 計算hash slot
計算hash slot的算法,就是根據key計算CRC16值,然后對16384取模,拿到對應的hash slot
用hash tag可以手動指定key對應的slot,同一個hash tag下的key,都會在一個hash slot中,比如set mykey1:{100}和set mykey2:{100}
6.1.3 hash slot查找
節點間通過gossip協議數據交換,就知道每個hash slot在哪個節點上
6.2 smart jedis
6.2.1 什么是smart jedis
基於重定向的客戶端,很消耗網絡IO,因為大部分情況下,可能都會出現一次請求重定向,才能找到正確的節點
所以大部分的客戶端,比如java redis客戶端,就是jedis,都是smart的
本地維護一份hashslot -> node的映射表,緩存,大部分情況下,直接走本地緩存就可以找到hashslot -> node,不需要通過節點進行moved重定向
6.2.2 JedisCluster的工作原理
在JedisCluster初始化的時候,就會隨機選擇一個node,初始化hashslot -> node映射表,同時為每個節點創建一個JedisPool連接池
每次基於JedisCluster執行操作,首先JedisCluster都會在本地計算key的hashslot,然后在本地映射表找到對應的節點
如果那個node正好還是持有那個hashslot,那么就ok; 如果說進行了reshard這樣的操作,可能hashslot已經不在那個node上了,就會返回moved
如果JedisCluter API發現對應的節點返回moved,那么利用該節點的元數據,更新本地的hashslot -> node映射表緩存
重復上面幾個步驟,直到找到對應的節點,如果重試超過5次,那么就報錯,JedisClusterMaxRedirectionException
jedis老版本,可能會出現在集群某個節點故障還沒完成自動切換恢復時,頻繁更新hash slot,頻繁ping節點檢查活躍,導致大量網絡IO開銷
jedis最新版本,對於這些過度的hash slot更新和ping,都進行了優化,避免了類似問題,這里向大家推薦一個java架構交流q裙:790047143
6.2.3 hashslot遷移和ask重定向
如果hash slot正在遷移,那么會返回ask重定向給jedis
jedis接收到ask重定向之后,會重新定位到目標節點去執行,但是因為ask發生在hash slot遷移過程中,所以JedisCluster API收到ask是不會更新hashslot本地緩存
已經可以確定說,hashslot已經遷移完了,moved是會更新本地hashslot->node映射表緩存的
7 高可用性與主備切換原理
原理,幾乎跟哨兵類似
7.1 判斷節點宕機
若一個節點認為另外一個節點宕機,即 pfail
- 主觀宕機
若多個節點都認為另外一個節點宕機,即 fail
- 客觀宕機
跟哨兵的原理幾乎一樣,sdown - odown
在 cluster-node-timeout
內,某個節點一直沒有返回 pong
,那么就被認為 pfail
若一個節點認為某個節點 pfail
,那么會在 gossip ping
消息中, ping
給其他節點,若 超過半數 的節點都認為 pfail
,那么就會變成 fail
7.2 從節點過濾
對宕機的master node,從其所有的slave node中,選擇一個切換成master node
檢查每個slave node與master node斷開連接的時間,如果超過了
cluster-node-timeout * cluster-slave-validity-factor
那么就沒有資格切換成master,這個也跟哨兵是一樣的,從節點超時過濾的步驟
7.3 從節點選舉
哨兵:對所有從節點進行排序,slave priority,offset,run id
每個從節點,都根據自己對master復制數據的offset,設置一個選舉時間,offset越大(復制數據越多)的從節點,選舉時間越靠前,優先進行選舉
所有的master node開始slave選舉投票,給要選舉的slave投票,如果大部分
master node(N/2 + 1)
都投票給了某從節點,那么選舉通過,該從節點可以切換成master
從節點執行主備切換,從節點切換為主節點
7.4 與哨兵比較
整個流程跟哨兵相比,非常類似,所以說,redis cluster功能強大,直接集成了replication和sentinal的功能