Redis(三十二)集群:集群中如何执行命令与重新分片原理

计算key的CRC-16校验和,然后通过与16383的与运算,得出一个比16383小的值(16383对应的是槽位的数量,不能超过这个值)

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


当计算出槽值之后,节点就会检查自己在clusterState.slots数组(前面提到过该数组存储集群中所有节点负责处理的槽)对应的索引对应的值是否为自己(ClusterNode)

  • 如果clusterState.slots[i]等于clusterState.myself,那么说明槽i是由当前节点负责,节点可以执行客户端的命令

  • 如果不等于,那么就说明不是由当前节点负责,节点会根据clusterStats.slots[i]指向的clusterNode结构所记录的节点IP和端口号,向客户端发送一个MOVED错误,指向客户端转向至正确的节点

MOVED错误


下面,我们看看这个MOVED错误是怎么生成的

当节点发现键所在的槽并非由自己负责处理的时候,节点就会向客户端返回一个MOVED错误,指向客户端转向至正在负责槽的节点

MOVED错误格式为

MOVED : //slot表示键的所在槽 ip和port是正确的节点

一个集群客户端(连接上集群上某个节点的客户端)通常会与集群中的多个节点建立套接字(套接字其实就是域名加端口)连接

  • 如果前面未与转向的节点进行连接,则要进行套接字连接,然后再进行转向

  • 如果已经连接过,直接换一个套接字去发送命令

注意:MOVED错误会被客户端隐藏起来,即不会被打印出来,而是自动进行转向,所以是看不见MOVED错误的

节点数据库的形成


集群节点保存键值对以及键值对过期时间的方式,跟前面讲过的Redis单机服务器是一样的,以及键对过期时间的方式也是完全相同的。

但这里要注意的是,节点数据库只可以使用0号数据库(Redis有16个数据库,0~15),而单机服务器是没有限制的,可以随意切换

另外,键值对除了保存在数据库外,还需要额外去记录键与槽之间的关系(一个节点可能指派了多个槽,那么这些键在槽中怎么存储)

在clusterState结构中会有一个slots_to_keys属性去保存键与槽之间的关系,底层是一个跳跃表

typedef clusterState(

//…

zskiplist *slots_to_keys;

//…

)clusterState;

slots_to_keys属性

底层为跳跃表,每个节点的分值(score)都是一个槽号,而每个节点的成员(member)都是一个数据库键(根据member排序,member不可以重复,但分支score可以重复)

  • 当节点往数据库添加一个新的键值对时,节点就会将这个键以及键的槽号关联在slots_to_keys跳跃表

  • 当节点删除数据库中的某一个键值对时,节点就会在slots_to_keys跳跃表解除被删除键与槽号的关联

忘记跳跃表,回看前面的zset底层原理(跳跃表)

重新分片


Redis集群的重新分片操作是指:将任意数量已经指派给某个节点(源节点)的槽改为指派给另一个节点(目标节点),并且相关槽所关联的键值对也要从源节点发送到目标节点

这里要注意的是,重新分片的操作是在线上执行的,集群不需要下线也是可以继续处理的,也就是源目标与目标节点都会继续处理重新分片的命令请求

重新分片的实现原理

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

下面就来看看redis-trib对集群的单个槽slot进行重新分片的步骤

  1. redis-trib对目标节点发送cluster setslot IMPORTING <source_id>命令,让目标节点准备好从源节点(source_id)导入属于槽slot的键值对

  2. redis-trib对源节点发送cluster setslot MIGRATING <target_id>命令,让源节点准备好将属于槽slot的键值对发送给目标节点(前两步都是准备工作)

  3. redis-trib向源节点发送**cluster getkeysinslot **命令,获得最多count个属于槽slot键值对的键名(key name)

  4. redis-trib遍历第三步发来的所有键名,根据每一个键名去向源节点发送**MIGRATING <target_ip> <target_port> <key_name> 0 **命令,将源节点中所有被选中的键值对从源节点迁移到目标节点

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

分享一些资料给大家,我觉得这些都是很有用的东西,大家也可以跟着来学习,查漏补缺。

《Java高级面试》

《Java高级架构知识》

《算法知识》

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
wg-1713378899691)]

《算法知识》

[外链图片转存中…(img-xN1uewRD-1713378899692)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值