Redis集群的節點通信原理


Redis集群搭建中,數據如何在節點分布的原理,下面來介紹一下節點之間是如何進行通信(節點握手)

一、基礎通訊原理

1、維護集群的元數據的兩種方案介紹及對比

在分布式存儲中需要提供維護節點元數據信息的機制,所謂元數據是指:節點負責哪些數據,是否出現故障等狀態信息。常見的元數據維護方式分為:集中式和P2P方式

  1. 集中式
    • 優點 :元數據的更新和讀取,時效性非常好,一旦元數據出現了變更,立即就更新到集中式的存儲中。
    • 缺點 :所有的元數據的更新壓力全部集中在一個地方,可能導致元數據的存儲有壓力。
  2. gossip
    • 優點 :元數據的更新比較分散,不是集中在同一個地方,更新請求會陸陸續續到達所有節點上去更新,有一定的延時,降低了壓力。
    • 缺點 :元數據更新有延時,可能會導致集群的一些操作會有一些滯后。

集中式示例圖-1:

集群元數據集中式存儲的典型代表就是storm:

集中式示例圖-2:假如redis cluster采用集中式存儲元數據如下圖:

 

P2P方式的gossip的redis cluster方式示例圖-3:

 

 

 2、redis cluster節點間采用gossip協議進行通訊

回到redis cluster,Redis集群采用P2P的Gossip(流言)協議,跟集中式不同,不是將集群元數據(節點信息、hashslot->node之間的映射表關系,還有master->slave之間關系,故障的信息等)集中存儲在某個節點上,Gossip協議工作原理就是節點彼此不斷通信交換信息,一段時間后集群的所有的節點都會有完整的(集群)信息,這種方式類似流言傳播

節點之間通信示意圖

 

 

3、10000端口

每個節點都有一個專門用於節點間通信的端口號,就是自己提供服務的端口號+10000。每個節點每隔一段時間都會往另外幾個節點發送ping消息,同時其他節點接收到ping之后會返回pong消息。

4、節點間交換的信息

包含故障信息,節點的增加和移除,hash slot信息等等。


二、Gossip消息

Gossip協議的主要職責就是信息交換。信息交換的載體就是節點彼此發送的Gossip消息,常用的Gossip消息可分為:ping消息、pong消息、meet消息、fail消息

  • meet消息:用於通知新節點加入(某個節點發送meet給新加入的節點,讓新節點加入集群中,然后新節點就會開始與其他節點進行通信)。消息發送者通知接收者加入到當前集群,meet消息通信正常完成后,接收節點會加入到集群中並進行周期性的ping、pong消息交換
    •   例如:執行redis-trib.rb add-node 命令時,其實內部就是發送了一個gossip meet消息,給新加入的節點,通知那個節點去加入我們的集群
  • ping消息:集群內交換最頻繁的消息,集群內每個節點每秒向多個其他節點發送ping消息,用於檢測節點是否在線和交換彼此狀態信息。ping消息發送封裝了自身節點和部分其他節點的狀態數據
    •   ping消息深入

      ping很頻繁,而且要攜帶一些元數據,所以可能會加重網絡負擔

      每個節點每秒會執行10次ping,每次會選擇5個最久沒有通信的其他節點

      當然如果發現某個節點通信延時達到了cluster_node_timeout / 2,那么立即發送ping,避免數據交換延時過長,落后的時間太長了

      比如說,兩個節點之間都10分鍾沒有交換數據了,那么整個集群處於嚴重的元數據不一致的情況,就會有問題

      所以cluster_node_timeout可以調節,如果調節比較大,那么會降低發送的頻率

      每次ping,一個是帶上自己節點的信息,還有就是帶上1/10其他節點的信息,發送出去,進行數據交換

      至少包含3個其他節點的信息,最多包含總節點-2個其他節點的信息

  • pong消息:當接收到ping、meet消息時,作為響應消息回復給發送方確認消息正常通信。pong消息內部封裝了自身狀態數據。節點也可以向集群內廣播自身的pong消息來通知整個集群對自身狀態進行更新,也可以用於信息廣播和更新
  • fail消息:當節點判定集群內另一個節點下線時,會向集群內廣播一個fail消息,其他節點接收到fail消息之后把對應節點更新為下線狀態

接收節點會解析消息內容並根據自身的識別情況做出相應處理,對應流程:

  • 解析消息頭過程:消息頭包含了發送節點的信息,如果發送節點是新節點且消息是meet類型,則加入到本地節點列表;如果是已知節點,則嘗試更新發送節點的狀態,如槽映射關系、主從角色等狀態
  • 解析消息體過程:如果消息體的clusterMsgDataGossip數組包含的節點是新節點,則嘗試發起與新節點的meet握手流程;如果是已知節點,則根據cluster MsgDataGossip中的flags字段判斷該節點是否下線,用於故障轉移

三、節點通訊優化

節點選擇
由於內部需要頻繁地進行節點信息交換,而ping/pong消息會攜帶當前節點和部分其他節點的狀態數據,勢必會加重帶寬和計算的負擔。Redis集群內節點通信采用固定頻率(定時任務每秒執行10次)。因此節點每次選擇需要通信的節點列表變得非常重要。通信節點選擇過多雖然可以做到信息及時交換但成本過高。節點選擇過少會降低集群內所有節點彼此信息交換頻率,從而影響故障判定、新節點發現等需求的速度。因此Redis集群的Gossip協議需要兼顧信息交換實時性和成本開銷,

選擇發送消息的節點數量

集群內每個節點維護定時任務默認每秒執行10次,每秒會隨機選取5個節點找出最久沒有通信的節點發送ping消息,用於保證Gossip信息交換的隨機性。每100毫秒都會掃描本地節點列表,如果發現節點最近一次接受pong消息的時間大於cluster_node_timeout/2,則立刻發送ping消息,防止該節點信息太長時間未更新。根據以上規則得出每個節點每秒需要發送ping消息的數量=1+10*num(node.pong_received>cluster_node_timeout/2),因此cluster_node_timeout參數對消息發送的節點數量影響非常大。當我們的帶寬資源緊張時,可以適當調大這個參數,如從默認15秒改為30秒來降低帶寬占用率。過度調大cluster_node_timeout會影響消息交換的頻率從而影響故障轉移、槽信息更新、新節點發現的速度。因此需要根據業務容忍度和資源消耗進行平衡。同時整個集群消息總交換量也跟節點數成正比。

消息數據量

每個ping消息的數據量體現在消息頭和消息體中,其中消息頭主要占用空間的字段是myslots[CLUSTER_SLOTS/8],占用2KB,這塊空間占用相對固定。消息體會攜帶一定數量的其他節點信息用於信息交換,消息體攜帶數據量跟集群的節點數息息相關,更大的集群每次消息通信的成本也就更高,因此對於Redis集群來說並不是大而全的集群更好

 

 

四、面向集群的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的功能



https://blog.csdn.net/nihao12323432/article/details/81204499

https://www.cnblogs.com/jack1995/p/10915801.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM