Redis是一个高可用、高性能、高可扩展性的基于内存也支持持久化存储的key-value存储数据库。
集群相关的数据结构:
// cluster.h
// 保存当前节点与其他节点进行通讯所需的全部信息
typedef struct clusterLink {
// 链接创建时间
mstime_t ctime;
// TCP套接字描述符
int fd;
// 发送缓冲区,保存等待发送给其他节点的数据
sds sndbuf;
// 接受缓冲区,保存从其他节点收到的数据
sds rcvbuf;
// 与当前节点相连接的节点
struct clusterNode *node;
} clusterLink;
// cluster.h
// 集群节点结构体
typedef struct clusterNode {
// 节点创建时间
mstime_t ctime;
// 节点ID,长度为40,每一个字符都是一个16进制字符,通过随机数生成
char name[REDIS_CLUSTER_NAMELEN];
// 节点标识,标识节点是 Master 或 Slave
int flags;
// 节点当前的配置纪元
uint64_t configEpoch;
// REDIS_CLUSTER_SLOTS:整个集群分块的总数目,即16384
// Slots是一个二进制位数组(bitarray),数组长度为REDIS_CLUSTER_SLOTS/8=2048个字节
// 位值1表示对应slot的数据存储在当前节点,是0表示不在这个节点。
unsigned char slots[REDIS_CLUSTER_SLOTS/8];
// 当前节点所分配的 slot 总数
int numslots;
// 若当前节点为 Master,则表示相应 Slave 的数据
int numslaves;
// 指针数组,指向 Slave 节点
struct clusterNode **slaves;
// 指正数组,指向 Master 节点
struct clusterNode *slaveof;
// 最近一次发送 ping包的时间
mstime_t ping_sent;
// 最近一次接受 pong包的时间
mstime_t pong_received;
// 最近一次被设置成 fail状态的时间
mstime_t fail_time;
// 最近一次为某个 Salve 投票的时间
mstime_t voted_time;
// 最近一次从这个节点接收到复制偏移量的时间
mstime_t repl_offset_time;
// 当前节点的复制偏移量
PORT_LONGLONG repl_offset;
// 当前节点的 IP
char ip[REDIS_IP_STR_LEN];
// 当前节点的 Port
int port;
// 保存连接相关的信息
clusterLink *link;
// 一个链表,记录了所有其他节点对该节点的下线报告
list *fail_reports;
} clusterNode;
// cluster.h
// 节点状态信息
typedef struct clusterState {
// 当前节点
clusterNode *myself;
// 集群当前的配置纪元
uint64_t currentEpoch;
// 状态标识:OK?FAIL?
int state;
// 集群中至少拥有一个 slot 的 Master 的数目
int size;
// 整个集群所有节点,键:节点ID,值:clusterNode结构体
dict *nodes;
// 节点黑名单
dict *nodes_black_list;
// 记录从当前节点迁移至目标节点的 slot,以及迁移的目标节点
// migrating_slots_to[i] = NULL 表示slot i未被迁移
// migrating_slots_to[i] = clusterNode_A 表示slot i要从本节点迁移至节点 A
// REDIS_CLUSTER_SLOTS:16384
clusterNode *migrating_slots_to[REDIS_CLUSTER_SLOTS];
// 记录要从源节点迁移到本节点的 slot,以及进行迁移的源节点
// importing_slots_from[i] = NULL 表示slot i未进行导入
// importing_slots_from[i] = clusterNode_A 表示正从节点 A中导入slot i
clusterNode *importing_slots_from[REDIS_CLUSTER_SLOTS];
// 记录各节点所分配的 slot
// 例如 slots[i] = clusterNode_A表示slot i 由节点 A处理
clusterNode *slots[REDIS_CLUSTER_SLOTS];
// 跳跃表
zskiplist *slots_to_keys;
// -------------------以下这些域被用于进行故障转移选举
// 上次执行选举或者下次执行选举的时间
mstime_t failover_auth_time;
// 节点收到的投票数目
int failover_auth_count;
// True:当前节点已经向其他节点发送投票请求
int failover_auth_sent;
// Slave 在当前故障转移选举中的排名
int failover_auth_rank;
// 当前选举的纪元
uint64_t failover_auth_epoch;
// Slave 不能执行故障转移选举的原因
int cant_failover_reason;
// -------------------共用的手动故障转移状态
// 手动故障转移时限
mstime_t mf_end;
// -------------------Mater 节点的手动故障转移状态
// Slave 节点
clusterNode *mf_slave;
// -------------------Slave 节点的手动故障转移状态
// 指示手动故障转移是否可以开始的标志值
PORT_LONGLONG mf_master_offset;
// 非0表示开始为选举 Master 投票
int mf_can_start;
// -------------------以下字段由 Master使用,用于记录选举状态
// 最近一次投票的纪元
uint64_t lastVoteEpoch;
// clusterBeforeSleep() 需要做的事情
int todo_before_sleep;
// 通过 cluster bus 发送消息的数目
PORT_LONGLONG stats_bus_messages_sent;
// 通过 cluster bus 接收消息的数目
PORT_LONGLONG stats_bus_messages_received;
} clusterState;