《Redis设计与实现》第十七章总结二:集群之运转

《Redis设计与实现》第十七章总结一:集群之节点和槽

17.3 在集群中执行命令

16384个槽全部进行了指派之后,集群进入上线状态,此时客户端就可以向集群中的节点发送数据命令了

当客户端向节点发送与数据库键有关的命令时:
《Redis设计与实现》第十七章总结二:集群之运转

17.3.1 计算键属于哪个槽

计算给定键key属于哪个槽的算法:
《Redis设计与实现》第十七章总结二:集群之运转
CLUSTER KEYSLOT 可以查看给定键属于哪个槽,其实现为:
《Redis设计与实现》第十七章总结二:集群之运转

17.3.2 判断槽是否由当前节点负责处理

clusterState.slots中的项与clusterState.myself进行比较:
《Redis设计与实现》第十七章总结二:集群之运转

17.3.3 MOVED错误

格式为:MOVED < slot > < ip >:< port >

slot为key所在槽,ip和port是负责处理槽的节点的ip和端口号

客户端根据ip和端口转向至此节点的socket,重新发送命令

注意:集群模式的moved错误不会打印,因为集群可以进行处理;而单机模式则会,因为单机模式的客户端并不清楚moved错误的作用,不会自动转向,只会打印

17.3.4 节点数据库的实现

集群节点与单机服务器在数据库方面保存键值对以及键值对过期时间的方式相同

集群节点与单机服务器在数据库方面的区别一是:节点只能使用0号数据库,单机服务器则没有此限制

例子:列表键list(带有过期时间)、哈希键book(带有过期时间)、字符串键date
《Redis设计与实现》第十七章总结二:集群之运转
节点使用clusterState的slots_to_keys跳跃表来保存槽和键之间的关系:
《Redis设计与实现》第十七章总结二:集群之运转
[外链图片转存失败(img-MovrEAMT-1563274534269)(…/markdownPicture/assets/1563157228366.png)]

例子:数据同上:列表键list(带有过期时间)、哈希键book(带有过期时间)、字符串键date
《Redis设计与实现》第十七章总结二:集群之运转

17.4 重新分片

作用:更改节点
《Redis设计与实现》第十七章总结二:集群之运转
可以在线进行,集群不需要下线,源和目标节点都可以继续处理命令请求

  • 实现原理

由Redis集群管理软件redis-trib负责执行,通过向源节点和目标节点发送Redis提供的进行重新分片的命令来进行重新分片操作

redis-trib对集群的单个槽slot进行重新分片的步骤:
目标节点做好准备、源节点做好准备、获取源节点键值对、迁移到目标节点、重复执行3、4直到所有键值对迁移完毕、通知整个集群节点槽迁移的信息:
《Redis设计与实现》第十七章总结二:集群之运转
迁移键的过程:第3、4步
《Redis设计与实现》第十七章总结二:集群之运转

17.5 ASK错误

重新分片时,键值对可能还在源节点,可能到了目标节点

当客户端向源节点发送一个与数据库键有关的命令,且该命令要处理的键恰好就属于正在被迁移的槽时,运行流程如下:
《Redis设计与实现》第十七章总结二:集群之运转
注意:集群模式的ask错误不会打印,因为集群可以进行处理;而单机模式则会,因为单机模式的客户端并不清楚ask错误的作用,不会自动转向,只会打印;类似moved错误的处理过程

接下来讲解ASK实现原理,对比ask和moved的区别

17.5.1 CLUSTER SETSLOT IMPORTING命令的实现

”重新分片的步骤“的第一步命令:CLUSTER SETSLOT IMPORTING <source_id>,将当前节点(目标节点)clusterState.import_slots_from[i]的值设置为source_id所代表节点的clusterNode结构

clusterState结构的importing_slots_from数组记录了当前节点正在从其他节点导入的槽:
《Redis设计与实现》第十七章总结二:集群之运转
某个索引值i指向一个clusterNode结构,则代表当前节点正在从clusterNode所代表的节点导入槽i

例子:客户端向7003发送CLUSTER SETSLOT 16198 IMPORTING 9dfb4w1sd15w11ds…(7002的id),则7003为:
《Redis设计与实现》第十七章总结二:集群之运转

17.5.2 CLUSTER SETSLOT MIGRATING命令的实现

”重新分片的步骤“的第二步命令:CLUSTER SETSLOT IMPORTING <target_id>,将源节点clusterState.migrating_slots_to[i]的值设置为target_id所代表节点的clusterNode结构

clusterState的migrating_slots_to数组记录了当前节点正在迁移至其他节点的槽:
《Redis设计与实现》第十七章总结二:集群之运转
某个索引值i指向一个clusterNode结构,则代表当前节点正在将槽迁移至clusterNode所代表的节点

例子:客户端向节点7002发送CLUSTER SETSLOT 16198 MIGRAING 16516516ASD(7003的id),则7002为:
《Redis设计与实现》第十七章总结二:集群之运转

17.5.3 ASK错误的执行

如果节点收到一个关于键key的命令请求,且键key所属的槽i正好就指派给了这个节点:
1.如果节点在自己的数据库里找到键key,则执行客户端发送的命令
2.如果没有找到,则检查clusterState.migrating_slots_to[i],看键所属的槽i是否正在进行迁移,若是,则节点向客户端发送一个ASK错误,引导客户端到正在导入槽i的节点去查找键key

收到ASK错误的客户端执行的操作:
《Redis设计与实现》第十七章总结二:集群之运转
例子:客户端发送GET "love"给7002,此键在槽16198上,此槽正在迁移至7003
《Redis设计与实现》第十七章总结二:集群之运转

17.5.4 ASKING命令

任务:打开发送该命令的客户端的REDIS_ASKING标识,可以客户端手动发送;此标识是一次性的

作用:用于判断当前节点是否要执行客户端命令的流程中
《Redis设计与实现》第十七章总结二:集群之运转
例子:
假设7003正在导入7002的槽16198,则客户端向7003发送键命令,节点会返回moved错误,指引客户端转向7002;
如果客户端是先发送ASKING命令再发送键命令,则键命令会被7003执行;
此次执行过后,ASKING命令就失效了,若还是要发送键命令,则需要先发送ASKING

17.5.5 ASK和MOVED的区别

《Redis设计与实现》第十七章总结二:集群之运转
简易版:
《Redis设计与实现》第十七章总结二:集群之运转

上一篇:python sqlite3查询表记录


下一篇:github编程指南