redis cluster集羣架構詳解(十二)- 集羣通信

5.5.集羣通信

5.5.1. redis cluster 內部通信機制

1、基礎通信原理

(1)redis cluster節點間採取gossip協議進行通信

​ 跟集中式不同,不是將集羣元數據(節點信息,故障,等等)集中存儲在某個節點上,而是互相之間不斷通信,保持整個集羣所有節點的數據是完整的。

​ 維護集羣的元數據常用兩種方法,一種是集中式,另一種叫做gossip。

​ 集中式:好處在於,元數據的更新和讀取,時效性非常好,一旦元數據出現了變更,立即就更新到集中式的存儲中,其他節點讀取的時候立即就可以感知到; 不好在於,所有的元數據的跟新壓力全部集中在一個地方,可能會導致元數據的存儲有壓力。

​ gossip:好處在於,元數據的更新比較分散,不是集中在一個地方,更新請求會陸陸續續,打到所有節點上去更新,有一定的延時,降低了壓力; 缺點,元數據更新有延時,可能導致集羣的一些操作會有一些滯後

​ 我們剛纔做reshard,去做另外一個操作,會發現說,configuration error,達成一致。

(2)10000端口

​ 每個節點都有一個專門用於節點間通信的端口,就是自己提供服務的端口號+10000,比如7001,那麼用於節點間通信的就是17001端口。

每個節點每隔一段時間都會往另外幾個節點發送ping消息,同時其他節點接收到ping之後返回pong。

(3)交換的信息

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

2、gossip協議

gossip協議:所有節點都持有一份元數據,不同的節點如果出現了元數據的變更之後,就不斷將元數據發送給其他的節點,讓其他及誒單也進行元數據的變更。

gossip協議包含多種消息,包括ping,pong,meet,fail,等等。

消息 說明
meet 某個節點發送meet給新加入的節點,讓新節點加入集羣中,然後新節點就會開始與其他節點進行通信。redis-trib.rb add-node ,其實內部就是發送了一個gossip meet消息,給新加入的節點,通知那個節點去加入我們的集羣
ping 每個節點都會頻繁給其他節點發送ping,其中包含自己的狀態還有自己維護的集羣元數據,互相通過ping交換元數據
pong 返回ping和meet,包含自己的狀態和其他信息,也可以用於信息廣播和更新
fail 某個節點判斷另一個節點fail之後,就發送fail給其他節點,通知其他節點,指定的節點宕機了

3、ping消息

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

​ 每個節點每秒會執行10次ping,每次會選擇5個最久沒有通信的其他節點,當然如果發現某個節點通信延時達到了cluster_node_timeout / 2,那麼立即發送ping,避免數據交換延時過長,如果落後的時間太長了,如兩個節點之間超過5分鐘沒有交換數據,那麼整個集羣處於嚴重的元數據不一致,這樣整個集羣會出現嚴重問題。所以cluster_node_timeout可以調節,如果調節比較大,那麼會降低發送的頻率。

​ 每次ping,都會帶上自己節點的信息,還帶上其他節點的信息(至少包含3個其他節點的信息,最多包含總節點-2個其他節點的信息)發送出去,進行數據交換。

5.5.2. 集羣發現:MEET

最開始時,每個Redis實例自己是一個集羣,我們通過cluster meet讓各個結點互相握手(handshake)。這也是Redis Cluster目前的一個缺點:**缺少節點的自動發現功能。**

組建一個真正的可工作的集羣,必須將各個獨立的節點連接起來,構成一個包含多個節點的集羣。

連接各個節點的工作使用CLUSTER MEET命令來完成。
CLUSTER MEET <ip> <port>

在這裏插入圖片描述

CLUSTER MEET命令實現:

1、節點Node1會爲節點Node2創建一個clusterNode結構,並將該結構添加到自己的clusterState.nodes字典裏面。

2、節點Node1根據CLUSTER MEET命令給定的IP地址和端口號,向節點Node2發送一條MEET消息。

3、節點Node2接收到節點Node1發送的MEET消息,節點Node2會爲節點A創建一個clusterNode結構,並將該結構添加到自己的clusterState.nodes字典裏面。

4、節點Node2向節點Node1返回一條PONG消息。

節點Node1將受到節點Node2返回的PONG消息,通過這條PONG消息節點Node1可以知道節點Node2已經成功的接收了自己發送的MEET消息。

5、之後,節點Node1將向節點Node2返回一條PING消息。

節點Node2將接收到的節點Node1返回的PING消息,通過這條PING消息節點Node2可以知道節點Node1已經成功的接收到了自己返回的PONG消息,握手完成。

6、之後,節點Node1會將節點Node2的信息通過Gossip協議傳播給集羣中的其他節點,讓其他節點也與節點Node2進行握手,最終,經過一段時間後,節點Node2會被集羣中的所有節點認識。

5.5.3. 集羣消息處理clusterProcessPacket

通過集羣消息處理函數 clusterProcessPacket處理消息:

1、更新接收消息計數器。

2、查找發送者節點並且不是handshake節點。

3、更新自己的epoch和slave的offset信息。

4、處理MEET消息,使加入集羣。

5、從goosip中發現未知節點,發起handshake。

6、對PING,MEET回覆PONG。

7、根據收到的心跳信息更新自己clusterState中的master-slave,slots信息。

8、對FAILOVER_AUTH_REQUEST消息,檢查並投票。

9、處理FAIL,FAILOVER_AUTH_ACK,UPDATE信息。

5.5.4. 定時任務clusterCron

定時任務clusterCron

1、對handshake節點建立Link,發送Ping或Meet。

2、向隨機幾點發送Ping。

3、查看是否需要做Failover。

4、統計並決定是否進行slave的遷移,來平衡不同master的slave數。

5、判斷所有pfail報告數是否過半數。

5.5.5. 心跳數據

發送消息頭信息Header(所負責slots的信息、主從信息、ip port信息、狀態信息)。

發送其他節點Gossip信息(ping_sent、 pong_received、ip,、port信息、狀態信息,比如發送者認爲該節點已經不可達,會在狀態信息中標記其爲PFAIL或FAIL)。

clusterMsg結構的currentEpoch、sender、myslots等屬性記錄了發送者自身的節點信息,接收者會根據這些信息,在自己的clusterState.nodes字典裏找到發送者對應的clusterNode結構,並對結構進行更新。

Redis集羣中的各個節點通過Gossip協議來交換各自關於不同節點的狀態信息,其中**Gossip協議由MEET、PING、PONG三種消息實現**,這三種消息的正文都由兩個clusterMsgDataGossip結構組成。

各個節點發送心跳數據如下序列圖:

在這裏插入圖片描述

1、每次發送MEET、PING、PONG消息時,發送者都從自己的已知節點列表中隨機選出兩個節點(可以是主節點或者從節點),並將這兩個被選中節點的信息分別保存到兩個結構中。

2、當接收者收到消息時,接收者會訪問消息正文中的兩個結構,並根據自己是否認識clusterMsgDataGossip結構中記錄的被選中節點進行操作:

  (1)如果被選中節點不存在於接收者的已知節點列表,那麼說明接收者是第一次接觸到被選中節點,接收者將根據結構中記錄的IP地址和端口號等信息,與被選擇節點進行握手。

  (2)如果被選中節點已經存在於接收者的已知節點列表,那麼說明接收者之前已經與被選中節點進行過接觸,接收者將根據clusterMsgDataGossip結構記錄的信息,對被選中節點對應的clusterNode結構進行更新。

5.5.6. 數據結構

1、clusterNode結構

clusterNode結構保存了一個節點的當前狀態,比如節點的創建時間,節點的名字,節點當前的配置紀元,節點的IP和地址等。

1)slots:位圖,由當前clusterNode負責的slot爲1。

2)salve, slaveof:主從關係信息。

3)ping_sent, pong_received:心跳包收發時間。

4)clusterLink *link:節點間的連接。

5)list *fail_reports:收到的節點不可達投票。

2、clusterState結構

clusterState結構記錄了在當前節點的集羣目前所處的狀態。

1)myself:指針指向自己的clusterNode。

2)currentEpoch:當前節點的最大epoch,可能在心跳包的處理中更新。

3)nodes:當前節點記錄的所有節點,爲clusterNode指針數組。

4)slots:slot與clusterNode指針映射關係。

5)migrating_slots_to,importing_slots_from:記錄slots的遷移信息。

6)failover_auth_time,failover_auth_count,failover_auth_sent,failover_auth_rank,failover_auth_epoch:Failover相關信息。

3、clusterLink結構

clusterLink結構保存了連接節點所需的有關信息,比如套接字描述符,輸入緩衝區和輸出緩衝區。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章