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结构保存了连接节点所需的有关信息,比如套接字描述符,输入缓冲区和输出缓冲区。

发布了155 篇原创文章 · 获赞 23 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/makyan/article/details/104798725