slots 数组包含 16384 个项 , 每个数组项都是一个指向 clusterNode 结构的指针:
- 如果 slots[i] 指针指向 NULL,那么表示槽 i 尚未指派给任何节点 。
- 如果 slots[i] 指针指向一个 clusterNode 结构,那么表示槽 i 已经指派给了 clusterNode 结构所代表的节点 。
- 如果节点只使用 clusterNode.slots 数组来记录槽的指派信息,那么为了知道槽 i 是否已经被指派,或者槽 i 被指派给了哪个节点,程序需要遍历 clusterState.nodes 字典中的所有 clusterNode 结构,检查这些结构的 slots 数组 , 直到找到负责处理槽 i 的节点为止 , 这个过程的复杂度为 O(N) , 其中 N 为 clusterState.nodes 字典保存的 clusterNode 结构的数量 。
- 而通过将所有槽的指派信息保存在 clusterState.slots 数组里面,程序要检查槽 i 是否已经被指派 , 又或者取得负责处理槽 i 的节点,只需要访问 clusterState.slots[i] 的值即可,这个操作的复杂度仅为 O(1) 。
客户端向集群的节点发送命令在对数据库中的 16384 个槽都进行了指派之后,集群就会进入上线状态,这时客户端就可以向集群中的节点发送数据命令了 。
当客户端向节点发送与数据库键有关的命令时,接收命令的节点会计算出命令要处理的数据库键属于哪个槽,并检查这个槽是否指派给了自己:
- 如果键所在的槽正好就指派给了当前节点,那么节点直接执行这个命令 。
- 如果键所在的槽并没有指派给当前节点,那么节点会向客户端返回一个 moved 错误,指引客户端转向(redirect)至正确的节点,并再次发送之前想要执行的命令 。
def slot_number(key):return CRC16(key) & 16383
其中 CRC16 (key) 语句用于计算键 key 的 CRC-16 校验和,而 &16383 语句则用于计算出一个介于 0 至 16383 之间的整数作为键 key 的槽号 。使用 cluster keyslot < key > 命令可以查看一个给定键属于哪个槽,这个命令就是通过调用上面给出的槽分配算法来实现的 。
2、判断槽是否由当前节点负责处理当节点计算出键所属的槽 i 之后,节点就会检查 clusterState.slots 数组中的项 i,判断键所在的槽是否由自己负责:
- 如果 clusterState.slots[i] 等于 clusterState.myself,那么说明槽 i 由当前节点负责,节点可以执行客户端发送的命令 。
- 如果 clusterState.slots[i] 不等于 clusterState.myself,那么说明槽 i 并非由当前节点负责,节点会根据 clusterState.slots[i] 指向的 clusterNode 结构所记录的节点 IP 和端口号,向客户端返回 moved 错误 , 指引客户端转向至负责处理槽 i 的节点 。
moved 错误的格式为:moved < slot > < ip > : < port > 。其中 slot 为键所在的槽,而 ip 和 port 则是负责处理槽 slot 的节点的 IP 地址和端口号 。
当客户端接收到节点返回的 moved 错误时,客户端会根据 moved 错误中提供的 IP 地址和端口号,转向至负责处理槽 slot 的节点,并向该节点重新发送之前想要执行的命令 。
一个集群客户端通常会与集群中的多个节点创建套接字连接,而所谓的节点转向实际上就是换一个套接字来发送命令 。如果客户端尚未与想要转向的节点创建套接字连接,那么客户端会先根据 moved 错误提供的 IP 地址和端口号来连接节点,然后再进行转向 。
被隐藏的 moved 错误:集群模式的 redis-cli 客户端在接收到 moved 错误时 , 并不会打印出 moved 错误,而是根据 moved 错误自动进行节点转向,并打印出转向信息,所以我们是看不见节点返回的 moved 错误的 。但是,如果我们使用单机(stand alone)模式的 redis-cli 客户端,moved 错误就会被客户端打印出来 。这是因为单机模式的 redis-cli 客户端不清楚 moved 错误的作用,所以它只会直接将 moved 错误直接打印出来 , 而不会进行自动转向 。
节点数据库的实现集群节点保存键值对以及键值对过期时间的方式 , 与单机 Redis 服务器保存键值对以及键值对过期时间的方式完全相同 。节点和单机服务器在数据库方面的一个区别是 , 节点只能使用 0 号数据库,而单机 Redis 服务器则没有这一限制 。
推荐阅读
- R数据分析:孟德尔随机化实操
- JavaScript常用工具函数
- Redis系列10:HyperLogLog实现海量数据基数统计
- MySQL数据库的性能分析 ---图书《软件性能测试分析与调优实践之路》-手稿节选
- 如何通过Java导出带格式的 Excel 数据到 Word 表格
- 砰砰军团数据处理谜题通关图文攻略汇总-砰砰军团数据谜题攻略大全
- Vue3实现动态导入Excel表格数据
- undefined,null,boolean类型 第一百零七篇:基本数据类型
- rabbitmq docker安装消息队列及数据库(mongo、mysql)
- 苹果手机如何刷机还原(苹果输错10次密码抹掉数据会怎样)