背景
这篇是对黄建宏的总结和学习笔记。
完整流程
客户端、节点1、节点2之间的关系?
1.客户端连接节点1
2.客户端发送加入集群命令给连接上的节点1
Cluster meet 节点2ip 节点2port
3.节点1把节点2加入集群
所谓加入集群,其实也就是,给每个节点建立一个数据结构,数据结构包含了哪些槽。
如何给节点添加槽?
也是客户端——节点。
客户端发送添加槽命令。
命令的具体格式是:addslots 槽编号。
细节
具体细节是客户端发送命令到节点。命令格式如下:
1.命令
2.哪个节点IP
3.哪个槽
有两个地方保存了槽/节点?
哪两个?
1.单个节点的槽
2.所有槽
第一种,数据结构是节点数据结构的数据(槽数组,即二进制位数组)。
第二种,是集群数据结构的数据(二进制位数组)。
现在的问题是,为什么要搞两种?
因为,第一种是用于节点之间互相通信,告知对方我有哪些槽,然后对方就把你的槽保存起来。
第二种是,用于查找某一个槽是在哪一个节点,本质上第一种也可以查找到,但是需要遍历,所以实际上。这又是一个用空间换时间的问题。
所谓槽slot?就是一个bit,就是一个位,二进制。
传播?1.为什么要传播 2.怎么传播?
传播的目的是,使得每个节点都保存/知道了每个槽slot是指向哪一个节点。或者叫告知别的节点,我有哪些槽,具体实现是通过命令,节点1——节点2。
具体实现?二进制bit位。
具体保存的数据结构是,每个节点,包括当前节点自己,都有一个数据结构存放这些数据。
集群是否上线?
集群是有下线和上线的状态的:
1.下线
2.上线
不同状态,只能做不同的事。
例如,下线的时候,你得先让集群上线。上线的标志就是,所有槽分配完毕,一个都不能剩下,否则状态字段就是下线。
上线之后,就可以发送更多的命令了。比如,数据命令。所谓数据命令,就是写数据啊读数据的命令。
如何计算key属于哪个槽编号?
步骤
1.先计算Hash
2.Hash值和总槽数量进行按位与
总结
像这种负载均衡,一般都是采用Hash方法,即使不是Hash,也是在Hash的基础之上再进行按位与运算。
注意
Redis的Hash,不是一般的Hash,而是crc,其实也是一种Hash算法,本质上都是为了尽可能地得到一个唯一的值。
如何重定向?
就是客户端从某个节点读数据的时候,发现该数据不在当前节点,这个时候就要重定向。
具体怎么做?
当然是根据IP/port,如果错误,就会返回正确的IP/port,因为每个节点都保存命了所有的槽/节点。
注意
这里还有个问题,就是客户端与节点的通信。客户端与节点的通信,本质上都是TCP套接字建立连接,而且一个客户端可能也可以同时和多个节点连接/建立套接字。
如果重定向的时候,发现新的节点没有建立连接,就先建立连接,否则就直接通信。
key+槽+多个指针是跳跃链表
即存储key+槽+多个指针,使用的数据结构是跳跃链表skiplist。
跳跃链表的节点,包含的字段有:
1.value,即数据
这里是key
2.score,即分数,用于排序
这里是槽编号
3.指针,多级

切换槽到新的节点
整个流程

说明
有专门的功能模块redistrib,来处理切换槽到新的节点。
槽的数据迁移完之后,其他节点(非源节点和目标节点)怎么知道槽已经切换节点?
通过消息。
具体一点?书上没讲清楚,这个地方。
另外,所谓的分片,就是分配槽,片就是槽,一个片就是一个槽。明明概念里是叫槽,非要整出来一个新名词,看着让人烦。
选举算法
集群和哨兵是两套不同的实现高可用/集群的机制。
1.哨兵
是哨兵选leader哨兵,leader哨兵再选从节点。
2.集群
如何判断一个主节点是否挂了?
选举机制/算法。
就是所有的主节点之间互相投票。
这个时候是没有哨兵的,那么就只能在主数据节点之间互相投票选举,所谓投票选举,其实就是互相两两之间进行投票,且只能投给一个人,哪个得票数最先过半,就胜出。
除了没有哨兵节点,和不是哨兵节点来选举从数据节点以外,其他都差不多。
但是,本质上,选举算法是一样的,不管是哨兵机制的哨兵内部选leader哨兵,还是集群机制的判断某个主节点是否下线,还是其他的选举,只要是投票选举,并且只能选一个人,那么就是计算最终得票数量,最先过半,就胜出。
还有一个问题,就是由谁来广播哪个节点下线?
因为虽然是投票,但是最终是有一个节点标记下线节点,而且这个节点需要把下线节点这个消息广播出去。但是这个标记下线节点和广播消息的节点,是怎么选出来的?按id排序或者其他什么排序,参考哨兵机制下的选从节点。
广播的消息,主要两个数据:1.我已经升级成为新的主节点 2.旧的主节点已经下线。
消息
五种
1.拉别人加入集群Cluster Meet
2.请求ping
3.响应pong
4.fail
5.publish
Gossip协议?
参考
黄建宏