redis cluster是redis提供的集群模式。
1.redis cluster的架構
①可以有多個master node,每個master node 都可以掛載多個slave node。
②讀寫分離的架構,對應每個master node來說,寫就寫到master node,讀就從master node對應的slave node去讀。
③高可用。每個master node都有多個 slave node,如果master node掛了,redis cluster機制就會自動將某個slave node切換成 master node。
所以redis cluster是 多master + 讀寫分離 + 高可用 的。只要基於edis cluster去搭建集群,就可以達到搭建 replication復制+主從架構+讀寫分離+哨兵集群+高可用的 集群架構。
2.redis cluster和replication+sentinal
①輸入數據量很少,主要是承載高並發的場景,單機就可以了。
②replication只有一個master node節點,多個slave node節點,所有節點上面的數據是一樣的,所有它可以提高讀請求的吞吐量,然后可以搭建一個Sentinal集群去保證高可用,但是他無法去擴容數據的存儲量。
③redis cluster,可以有多個master node去存儲不同的數據,所有他適合數據量特別大的場景,而且它可以不用Sentinal集群就可以保證高可用。
3.數據分布算法
(1)redis cluster機制
①自動將數據分片,每個master node上面存放一部分數據。
②提供內置的高可用支持,部分master node不可用時,還是可以工作的。
③在redis cluster架構中,每個redis要開發兩個端口,比如一個是6379,那么另一個就是加10000之后的端口號,比如16379。16379端口是用來進行節點間通信的,也就是cluster bus集群總線,cluster bus的通信用來進行故障檢測、配置更新、故障轉移授權等操作。
④cluster bus用來一種二進制的協議,主要用於節點間進行高效的數據交換,占用更少的網絡帶寬和處理時間。
(2)最古老的hash算法
原理 :來了一個key之后,計算hash值,然后對master node節點數量取模,將數據哈希到不同的節點。
存在問題 :會導致大量緩存重建的問題。這種情況下,一旦一個master宕機了,所有的請求過來之后,就會對新的節點數量(原節點數量-1)去取模,然后去相應的node取數據,這樣會導致請求走不到原本路由到的實例上面去,導致大量的key瞬間全部失效。
(3)一致性hash算法(自動緩存遷移)
原理 :將所有master node落在一個圓環上面,然后,有一個key過來之后。同樣就是hash值,然后會用hash值在圓環對應的各個點上(每個點都有一個hash值)去對比,看hash值落在那個位置,落在圓環上面以后,就會順時針旋轉去尋找距離自己最近的一個節點,數據的存儲於讀取都在該節點進行。
優勢 :保證了任何一個master宕機,只會影響之前在那個master上面的數據,因為照着順時針走,全部在之前的master上面找不到了,master也宕機了,就會繼續順着順時針走到下一個master節點去。這樣就只會有一部分數據丟失。
存在問題 :假如有3個master,那么就會丟失1/3的數據,這也是很多的。還會存在 緩存熱點的問題。 緩存熱點問題 :可能在某個hash區間內存在大值特別多,那么就會導致大量的數據進入同一個master,造成該master出現瓶頸。
(4)一致性哈希(自動緩存遷移)+虛擬節點(自動負載均衡)
為了解決上面的問題,在一致性哈希的基礎上增加了虛擬節點方案來處理。
原理 :給每個master都做了一部分的虛擬節點,這部分虛擬節點也分布在這個圓環上面,那么在每個區間內,大量的數據就會均勻的分布在不同節點上。
(5)hash slot算法
原理 :①redis cluster有固定的16384個hash slot,每個key計算CRC16值,然后多
16384取模,可以獲取key對應的hash slot。
②redis cluster中每個master節點都會持有一部分hash slot。
③增加一個master,就講其他master的hash slot移動一部分給新加入的master。
④減少一個master,就將他的hash slot移動到其他master上面去。
⑤移動hash slot的成本是非常低的。
⑥客戶端的api是可以指定hash tag來讓數據走同一個hash slot的。
4.redis cluster的核心原理
(1)節點間的內部通信機制
1.基礎通信原理
①redis cluster節點間采取gossip協議進行通信。
跟集中式不同,不是將集群元數據(節點信息、故障等等)集中存儲在某個節點上,而是相互之間不斷通信,保持整個集群所有節點的數據是完整的。
②維護集群的元數據的兩種方式對比
A.集中式
優點 :元數據的更新和讀取,時效性非常好,一旦元數據出現了變更,立即就更新到集中式的存儲中。
缺點 :所有的元數據的更新壓力全部集中在一個地方,可能導致元數據的存儲有壓力。
B.gossip
優點 :元數據的更新比較分散,不是集中在同一個地方,更新請求會陸陸續續到達所有節點上去更新,有一定的延時,降低了壓力。
缺點 :元數據更新有延時,可能會導致集群的一些操作會有一些滯后。
③10000端口
每個節點都有一個專門用於節點間通信的端口號,就是自己提供服務的端口號+10000。每個節點每隔一段時間都會往另外幾個節點發送ping消息,同時其他節點接收到ping之后會返回pong消息。
④節點間交換的信息
包含故障信息,節點的增加和移除,hash slot信息等等。
2.gossip協議
gossip協議,即流言協議。gossip協議包含多種消息,包括ping,pong,meet,fail等等。
①ping: 每個節點都會頻繁的給其他節點發送ping,其中包括自己的狀態還有自己維護的集群元數據,互相通過ping交換元數據。
②meet:某個節點發送meet給新加入的節點,讓其加入進群中,然后新節點就會開始與其他節點進行通信。
③pong:作為ping和meet的響應,包含自己的狀態和其他信息,也可以用於信息廣播和更新。
④fail:某個節點判斷另一個節點fail之后,就會發送fail消息給其他節點,通知其他節點,指定的節點宕機了。
3.深入ping消息
①ping很頻繁,而且要攜帶一些元數據,所以會加重網絡負擔。
②每個節點每秒會執行10次ping,每次會選擇5個最久沒有通信的其他節點去通信。
③如何發現某個節點通信時延達到了 cluster_node_timeout/2,那么立即發送ping,避免數據交換延時太長,落戶的時間太多。
④可以調節 cluster_node_timeout的值,如果調節比較大。就會降低ping發送的概率。
⑤每次ping都會帶上自己的信息。還要帶上1/10其他節點的信息,發送出去進行交換。
⑥至少包含3個其他節點的信息,最多包含總節點-2個其他節點的信息。
(2)面向集群的jedis內部實現原理
1.基於重定向的客戶端
redis-cli c,自動重定向
①請求重定向
客戶端可能會挑選任意一個redis實例去發送命令,每個redis實例接收到命令之后,都會接受key對應的hash slot,如果在本地就在本地處理,否則返回moved給客戶端,讓客戶端進行重定向。
cluster keyslot mykey ,可以查看一個key對應的hash slot是什么。
用redis-cli的時候,可以加入-c參數,支持自動的請求重定向,redis-cli接收到moved之后,會自動重定向到對應的節點執行命令。
②計算hash slot
計算hash slot的算法,就是根據key計算CRC16值,然后對16384取模,拿到對應的hash slot。
用hash tag可以手動指定key對應的slot,同一個hash tag下的key,都會在一個hash slot中,比如set mykey1:{100}和set mykey2:{100}。
③hash slot查找
節點間通過gossip協議進行數據交換,就知道每個hash slot在那個節點上面了
2.smart jedis
①什么是smart jedis:
基於重定向的客戶端,很消耗網絡IO,因為大部分情況下,可能都會出現一次請求重定向,才能找到正確的節點。
所以大部分的客戶端,比如java redis客戶端,就是jedis,都是smart的。
本地維護一份hashslot -> node的映射表,緩存,大部分情況下,直接走本地緩存就可以找到hashslot -> node,不需要通過節點進行moved重定向。
②JedisCluster的工作原理
A:在JedisCluster初始化的時候,就會隨機選擇一個node,初始化hash slot到node的映射表,同時為每個節點創建一個JedisPool連接池。
B:每次基於JedisCluster執行操作,首先會在本地計算key的hash slot,然后在本地映射表中找到節點。
C:如果那個node真好還是持有那個hash slot,那么就OK。
D:如果JedisCluster API返回的是moved,那么利用該節點的數據,更新本地的hash slot 和node的映射表。
E:重復上面的步驟,知道找到對應的節點,如果重試超過5次,就會報錯,拋出JedisClusterMaxRedirectionException異常。
jedis老版本,可能會出現在集群某個節點故障還沒完成自動切換恢復時,頻繁更新hash slot,頻繁ping節點檢查活躍,導致大量網絡IO開銷。
jedis最新版本,對於這些過度的hash slot更新和ping,都進行了優化,避免了類似問題。
③hash slot遷移和ask重定向
A:如果hash slot正在進行遷移,那么會返回ask重定向給jedis,
B:jedis接收到ask重定向之后,會重新定位到目標節點去執行。
C:但是因為ask發生在hash slot遷移過程中,所以收到ask是不會更新hash slot本地緩存。
D:已經可以確定說hash slot已經遷移完了,moved是會更新本地hash slot到node的映射緩存的。
(3)高可用與主備切換原理
redis cluster的高可用原理,幾乎和哨兵時類似的。
1.判斷節點宕機
①如果一個節點認為另一個節點道濟,那么就是pfail,主觀宕機。
②如果多個節點都認為另外一個 節點宕機了,那就是fail,客觀宕機。
③在cluster-node-timeout內,某個幾點一直沒有返回pong,那么就認為pfail。
④如果一個節點認為某個節點pfail了,那么會在gossip ping消息中,發送給其他節點,如果超過半數的節點都認為pfail了,那就好變成fail。
2.從節點過濾
①對宕機的master node,從其所有的slave node中,選擇一個切換成master node。
②檢查每個slave node與master node斷開連接的時機,如果超過了cluster-node-timeout * cluster-slave-validity-factor,那么這個節點就沒有資格切換成 master node,直接被過濾。
3.從節點選舉
①每個從幾點,都根據自己對master復制數據的offset,來設置一個選舉時間,offset越大的從節點,選舉時間越靠前,優先進行選舉。
②所有的master node開始slave選舉投票,給要進行選舉的slave進行投票,如果大部分master node(N/2 + 1)都投票給了某個從節點,那么選舉通過,那個從節點可以切換成master node。
③從節點執行主備切換,從節點切換為主節點。
4.與哨兵進行比較
整個流程跟哨兵相比,非常類似,所以說,redis cluster功能強大,直接集成了replication和sentinal的功能