一、节点
通过CLUSTER MEET <ip> <port>可以指定对应节点到当前节点的集群中,通过cluster-enabled配置可以决定是否开启Redis服务器的集群模式
- 向节点A发送CLUSTER MEET B_ip B_port
- 收到命令的A为B创建一个clusterNode的结构,并将该结构存入自己的cluserState.nodes字典
- B收到A的消息后,也会为A创建一个clusterNode的结构,并将该结构存入自己的cluserState.nodes字典
- 随后,B向A返回一条PONG消息
- 收到PONG消息的A,给B发送一条PING消息,至此握手完成。
- 最后A会把节点B通过Gossip协议(每个节点都会随机选择几个节点发送Gossip消息,其他节点会再次随机选择其他几个节点接力发送消息。这样一段时间过后,整个集群都能收到这条消息。最大的好处是,即使集群节点的数量增加,每个节点的负载也不会增加很多,几乎是恒定的。)传播给集群的其他节点
二、槽指派
Redis集群的整个数据库会被分为16384个槽slot,数据库每个key都属于其中之一,集群每个节点都可以处理0-16384个slot。只有所有的slot都有节点处理,Redis集群才算上线状态,否则处于下线状态。
- 通过向节点发送CLUSTER ADDSLOTS <slot> [slot...] 可以把对应slot添加给对应节点,如CLUSTER ADDSLOTS 0 1 2 3 4 ... 5000。如果节点1-5000中任何一个槽已经被指配,则返回错误。
- clusterNode结构的slots(unsigned char slots[16384/8])属性和numslot记录了节点负责处理哪些槽。slots是一个二进制位数组,每一个位记录节点是否负责对应槽。
- 集群节点之间也会相互传播节点的槽指派信息,每个节点都会知道16384个槽分别被指派给了哪个节点。clusterState结构中的clusterNode *slots[16384]记录了每个槽分别指向那个节点
三、集群中执行命令
3.1
3.1.1
当向集群节点A发送命令get key,但是通过CRC16(key)&16383计算key对应的槽,当clusterState.slot[i]等于clusterState.myself,则槽是自己负责,否则向客户端返回MOVED错误,指引客户端转向正确的节点
3.1.2
一个集群客户端通常会与集群中多个节点创建套接字接口,MOVED节点转向只是换一个套接字发送命令
3.1.3
节点使用clusterState结构中slots_to_keys跳跃表记录槽和键之间的关系,其中键lst和book带有过期时间,每个节点的分值(score)表示一个槽号,节点成员(member)表示一个数据库键
跳跃表介绍1、2、3
跳跃表貌似只适用于sorted set数据类型??? 参看
3.2 重新分片
在重新分片过程中,集群对外没有任务变化,源节点和目标节点都可以处理请求
- 1.通过redis集群管理软件redis-trib对目标节点发送CLUSTER SETSLOT <slot> IMPORTING <source_id>,让目标节点好接受slot的键值对;
- 2.通过向源节点发送CLUSTER SESLOT <slot> MIGRATING <target_id>准备迁移至SLOT
- 3.向源节点发送CLUSTER GETKEYSINGSLOT <slot> <count>获取最多count个属于slot的键名
- 4.对于3获取的键名向源节点发送 MIGRATE <target_ip> <target_port> <key_name> 0 <timeout>迁移键
- 5.向集群节点发送CLUSTER SETSLOT <slot> NODE <target_id>表示槽slot已经指派给target_id了
MOVED错误表示槽的负责权已经从一个节点转移到另一个节点;ASK错误表示俩个节点正在进行槽迁移
集群中的节点通过发送MEET、PING、PONG、PUBLISH、FAIL消息来通信 - MEET消息:发送者接受客户端的CLUSTER MEET消息,就会向接受者发送MEET消息,请求接受者加入当前集群
- PING消息:集群内交换最频繁的消息,集群内每个节点每秒向多个其他节点发送ping消息,用于检测节点是否在线和交换彼此状态信息
- PONG:当接收到ping、meet消息时,作为响应消息回复给发送方确认消息正常通信。pong消息内部封装了自身状态数据。节点也可以向集群内广播自身的pong消息来通知整个集群对自身状态进行更新
- FAIL消息:当节点判定集群内另一个节点下线时,会向集群内广播一个fail消息,其他节点接收到fail消息之后把对应节点更新为下线状态
- publish:一个节点接受到publish命令,不但会执行,还会向集群广播这条publish命令,所有接受到消息的节点都会执行publish命令