Redis(三十):集群(一)

可以看到,普通Redis服务器有的功能,节点也会有

除此之外,像Sentinel一样,节点服务器也有属于节点状态结构(Sentinel有一个SentinelStat结构),ClusterNode、ClusterLink结构以及ClusterState结构里面

当然,服务器状态还是保存在RedisServer结构中

集群数据结构


clusterNode结构保存了一个节点的当前状态,比如节点的创建时间、节点的名字、节点当前的配置纪元(集群也有主从节点,也要进行故障转移)、节点的IP地址和端口号等等

当使用集群模式开启了服务器时,就代表这个服务器是一个节点,节点会用clusterNode结构来记录自己的状态,并为集群中的所有节点(主节点和从节点)都会去创建一个相应的clusterNode结构,用该结构去记录其他节点的状态

struct clusterNode(

//创建节点时间

mstime_t ctime;

//节点的名字

//由40个十六进制字符组成

char name[REDIS_CLUSTER_NAMELEN];

//节点标识

//用来区分节点是主还是从节点

//以及区分节点的状态(上线还是下线)

int flags;

//节点当前的配置纪元,用于实现故障转移

unit64_t configEpoch;

//节点的ip地址

char ip[REDIS_IP_STR_LEN];

//节点的端口号

int port;

//保存连接节点所需的有关信息(TCP建链连接)

clusterLink *link;

//…

)

前面提到过,ClusterNode结构之外,还有一个ClusterLink结构,从ClusterNode结构里面的属性看到,ClusterLink结构是被用在ClusterNode里面的,并用来保存连接节点所需的有关信息,比如套接字描述符,输入缓冲区和输出缓冲区

typedef struct clusterLink(

//连接的创建时间

mstime_t ctime;

//TCP套接字描述符(记录节点连接当前节点使用的套接字)

int fd;

//输出缓冲区(保存着等待发送给其他节点的消息)

sds sndbuf

//输入缓冲区(保存着从其他节点接收到的信息)

sds rcvbuf;

//与这个连接相关联的节点,如果没有的话就为NULL(也就是引用clusterLink的节点)

//相当于形成了一个互通

struct clusterNode *node;

)clusterLink

拓展

RedisClient结构与ClusterLink结构的相同与不同之处

相同之处在于,两者都有记录自己的套接字描述符和输入输出缓冲区

不同之处在于,RedisClient的套接字和缓冲区是用来连接客户端的(服务器根据这些去得到请求客户端的信息,通过输入缓冲区和输出缓冲区进行命令提取和回复),而ClusterLink是用来连接节点的(当前节点通过这个节点的ClusterNode里面的ClusterLink里面的信息进行连接,获取发来的消息或者发送回复)

最后,每一个节点都保存着一个ClusterState结构(上面提到的ClusterNode都是保存在ClusterState俩面的),该结构记录了在当前节点的视角下,集群目前所处的状态,例如集群是下线的还是上线,集群包含多少个节点,集群当前的配置纪元

typedef struct clusterState(

//指向当前节点的指针

clusterNode *myself;

//集群当前的配置纪元,用来实现故障转移的

uinit64_t currentEpoch;

//集群当前的状态,下线还是上线

int state;

//集群中处理槽的节点的数量

int size;

//集群节点名单(包括Myself)

//使用字典保存,键为节点的名字,值为节点对应的clusterNode结构

dict *nodes;

//…

)clusterState;

总结起来,集群数据结构大概如下所示

每个节点都有ClusterState去保存自己和其他集群节点的状态(ClusterNode),在ClusterNode中又保存着节点之间的连接信息(当前节点与保存的节点)

在这里插入图片描述

CLUSTER MEET命令的实现


经过上面的学习,已经知道集群的数据结构是怎样的,下面就看看Cluster Meet命令是怎么实现的

CLUSTER MEET命令的作用是,执行Cluster命令的A节点会将命令中指定的B节点给添加到A节点的集群中去,跟邀请别人进群差不多

CLUSTER MEET

节点A会先跟B进行握手,以此来确认彼此的存在,并未将来的进一步通信打好基础,下面就来看看握手的过程

  1. 节点A先为节点B创建一个ClusterNode结构,并将该结构添加到自己的ClusterState.nodes字典里面(现在还不知道节点B的名字,会以一个随机字符串来当节点B的名字,而且flags属性为REDIS_NODE_HANDSHAKE|REDIS_NODE_MEET状态,表明正在握手处理中而且等待MEET信息发送处理)

  2. 节点A根据命令里面给出的IP地址和PORT端口号,建立TCP连接,向节点B发送一条Meet信息(Meet信息是确认节点B是否存在,最后将REDIS_NODE_MEET标志清除,表明Meet信息已经发送了)

  3. 节点B顺利接收到节点A发送的Meet信息的话,节点B就会为节点A创建一个ClusterNode结构,并将该结构添加到自己的ClusterState.nodes字典里面**(MEET信息里面有节点A的port和ip地址,节点B根据这些信息去创建ClusterNode对象,但此时flag标志还是初始化为REDIS_NODE_HANDSHAKE,注意此时节点B也还是不知道节点A的名字)**

  4. 节点B添加完成之后,节点B会返回一条PONG信息(PONG信息里面还有节点B的名字)给节点A

  5. 节点A收到节点B返回的PONG信息,根据PONG信息可以知道节点B是从节点还是主节点,还有节点B的名字,根据这些信息去修改节点A的ClusterState.nodes字典里面的ClusterNode信息**(清除原来的REDIS_NODE_HANDSHAKE标记,然后根据主从信息,设置为REDIS_NODE_MASTER或者REDIS_NODE_SLAVE,然后将节点B的名字进行更新)**

  6. 节点A确认收到PONG信息之后,会返回一条PING信息给节点B

  7. 经过此步节点A与节点B就握手完成了

在这里插入图片描述

最后

最后,强调几点:

  • 1. 一定要谨慎对待写在简历上的东西,一定要对简历上的东西非常熟悉。因为一般情况下,面试官都是会根据你的简历来问的; 能有一个上得了台面的项目也非常重要,这很可能是面试官会大量发问的地方,所以在面试之前好好回顾一下自己所做的项目;
  • 2. 和面试官聊基础知识比如设计模式的使用、多线程的使用等等,可以结合具体的项目场景或者是自己在平时是如何使用的;
  • 3. 注意自己开源的Github项目,面试官可能会挖你的Github项目提问;

我个人觉得面试也像是一场全新的征程,失败和胜利都是平常之事。所以,劝各位不要因为面试失败而灰心、丧失斗志。也不要因为面试通过而沾沾自喜,等待你的将是更美好的未来,继续加油!

以上面试专题的答小编案整理成面试文档了,文档里有答案详解,以及其他一些大厂面试题目。

面试答案

三面头条+四面阿里+五面腾讯拿offer分享面经总结,最终入职阿里

三面头条+四面阿里+五面腾讯拿offer分享面经总结,最终入职阿里

三面头条+四面阿里+五面腾讯拿offer分享面经总结,最终入职阿里

不要因为面试失败而灰心、丧失斗志。也不要因为面试通过而沾沾自喜,等待你的将是更美好的未来,继续加油!

以上面试专题的答小编案整理成面试文档了,文档里有答案详解,以及其他一些大厂面试题目。

面试答案

[外链图片转存中…(img-HeyzFFIB-1719170724592)]

[外链图片转存中…(img-sxNDMd6H-1719170724593)]

[外链图片转存中…(img-gwWh4RXW-1719170724594)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值