Redis集群
Redis集群是Redis提供的分布式数据库方案,集群通过分片(sharding)来进行数据共享,并提供复制和故障转移功能。
节点
一个Redis集群通常由多个节点组成(运行在集群模式下的Reids服务器)
//连接各个节点的工作可以使用 CLUSTER MEET <IP><port>
向一个节点发送CLUSTER MEET命令,可以让node节点与ip和port所指定的节点进行握手(handshake),如果握手成功,那么node节点会将ip和port所指定的节点添加到node所在的集群中。
集群的数据结构
clusterNode结构保存了一个节点的当前状态:比如节点的创建时间、节点的名字、节点当前的配置级元、节点的IP和端口号等等。
每个节点都会使用一个clusterNode结构来记录自己的状态,并为集群中所有其他节点(包括主节点和从节点)都创建一个相应的clusterNode结构,以此来记录其他节点的状态。
struct clusterNode{ //创建节点的时间 mstime_t ctime; //节点的名字,由40个十六进制字符组成 char name[REDIS_CLUSTER_NAMELEN]; //节点标识,使用不同的标识值记录节点的角色,以及节点目前所处的状态 int flags; //节点当前的配置纪元,用于实现故障转移 uint64_t configEpoch; //节点的ip地址 char Ip[Redis_ip_str_len]; //节点的端口号 int port; //保存连接节点所需的有关信息 clusterLink *link; }
struct clusterLink{ //连接创建的时间 mstime_t ctime; //TCP 套接字描述符 int fd; //输出缓冲区,保存着等待发送给其它节点的消息 sds sndbuf; //输入缓冲区,保存着从其他节点接收到的消息 sds rcvbuf; //与这个连接相关联的节点,如果没有的话就为null struct clusternode * node; }
每个节点都保存着一个clusterState结构,这个结构记录了当前节点集群目前所处的状态
typedf struct clusterState{ //指向当前节点的指针 clusterNode *myself; //节点当前的配置纪元,用于实现故障转移 uint64_t configEpoch; //集群当前的状态:在线还是下线 int state; //集群中至少处理着一个槽的节点的数量 int size; //集群节点名单(包括myself) //字典的键为节点的名字,字典的值为节点对应的clusterNode指针 dict *nodes; }clusterState
CLUSTER MEET 命令的实现
以客户端向节点A发送CLUSTER MEET 命令,让节点A将节点B添加到集群中,收到命令的节点A将于节点B进行握手,以此来确认彼此的存在。
CLUSTER MEET <ip><port>
1.节点A会为节点B创建一个clusterNode结构,,并将该结构添加到自己的clusterState.Nodes字典里面 2.之后,节点A将根据CLUSTER MEET 命令给定的IP和端口号,向节点B发送一条MEET消息 3.如果一切顺利,节点B将收到节点A发送的MEET消息,节点B会为了节点A创建一个ClusterNode结构,并将该结构添加到自己的clusterState.Nodes字典里面 4.之后,节点B将向节点A返回一条PONG消息 5.如果一切顺利的话,那么节点A在收到节点B返回的PONG消息,通过这条PONG消息节点A可以知道节点B已经成功接收到了自己发送的MEET消息 6.之后,节点A将向节点B返回一条PING消息 7.如果一切顺利的话,节点B会接收到节点A返回的PING消息,通过这条PING消息节点B可以知道节点A已经成功地接收到了自己返回的PONG消息,握手成功。 8.之后节点A会将节点B的信息通过Gossip协议传播给集群中的其他节点,让其他节点也与节点B进行握手,最后节点B会被集群中所有节点认识。