Redis集群槽道原理

11 篇文章 0 订阅
3 篇文章 0 订阅

                               Redis集群槽道原理


目录

                               Redis集群槽道原理

一.槽道原理必须解决的问题

   问题一

  问题二

 二.槽道原理的结构

 二进制位序列可以判断结点的管理槽道权

集群中节点的二进制特点:

槽道的基础,两两互联,集群最大连接数为1000,到底为什么呢?

索引数组可以保存所有的槽道管理者信息

三.Redis集群槽道原理

四.调用集群命令cluster meet 节点碰撞

1.杀死所以进程,并且把生产的文档全部删除

2.启动对应的节点

3.启动完毕

4.节点握手

5.握手测试

6.全部加入进去  集群节点握手成功

7.分配槽道

8.写个脚本,循环分配槽道

9.在操作分配槽道的时候,如何初始化槽道 cluster addslots xxx

10.查看集群状态

11.添加从节点(默认添加的都是主节点)

12.槽道迁移(空槽道迁移)

13.非槽道迁移



一.槽道原理必须解决的问题

   问题一

  • 节点如何在取模算法获取的结果之后判断是否由当前节点管理这个槽道?

  问题二

  • 如果判断结果是不管理,如何获取正确的槽道所在的结点信息

 二.槽道原理的结构

内存中保存2中数据结构内容,维护所有与槽道,节点对应关系的计算

  • 16384位的二进制,本质2048个元素的byte数组,位序列
  • 16384个元素的数组对象,元素内容是引用变量,索引数组

 二进制位序列可以判断结点的管理槽道权

二进制中,可以利用对二进制的计算(位移计算),获取每一位的"下标"号,下标号是0-16383,每一个下标对应一个槽道号,每一个槽道号就可以在二进制中找到一个1/0的值,每一个节点中都会存储管理这样一个byte数组的位序列,通过对二进制的计算,获取槽道号对应的二进制值,1表示有管理权,0表示没有管理权.

举例: 

  set name ly   下标为6569   假设三个主节点分别是A(0-5461)B(5462-10086)C(10087-16383)  假如进入到A节点中获取最后一个槽道发现是5461之前的二进制都是1,说明超过5461之后的槽道不归A处理,就判断转发找到对应的B节点中 处理数据  哪如何判断的呢?是逐一判断的吗 还是直接找到的呢?

假设 上篇博客中,如上图5798槽道莫名其妙报错不想要了,我把这个槽道从B主节点中扔给A的话,在A中对应的二进制会改变,原来的0变为1

集群中节点的二进制特点:

  • 有槽道管理权主节点的二进制有值,所有二进制位的或运算是16384位个1
  • 而且每一位最多只有一个结点的二进制是1
  • 没有管理权的主节点和从节点:二进制位序列都是0

位移的介绍

>>x&1  保真   

  • key s输入的字符串数据 如:ly  
  • 因为只是简单模拟了所以设置8个槽道,没设置16384个槽道
  • bin 为槽道一共八个 循环是获取每一位的二进制的值  
  • 当key的二进制的值对应槽道号的值就只关注对应槽道,其二进制值为1
  • 因为Redis底层是用C写的,所以底层会对2048个元素的byte数组,位序列 

16384个元素,下标对应槽道号,每一个下标对应槽道号的元素内容是一个引用的对象,槽道号的管理者是谁,元素引用对象(变量)指向内存中节点点的对象.当二进制判断完成所有权,一旦发现不管理,就直接到数组中获取对应下标的元素变量拿到节点对象,ip,port,id,进行转发redirect逻辑;

结论:

  • 槽道是一个由两部分主要数据结构组成的计算逻辑;
  •  这两部分数据结构都是内存在创建集群时就出现的内存数据;

以上是解决问题一的答案


槽道的基础,两两互联,集群最大连接数为1000,到底为什么呢?

如上图,当我们搭建一个集群的时候,把对应的节点的信息都会加载进去,假设我们搭建三个主节点的集群,随便进入一个节点中都可以获取其他节点的信息,如上如所说,每新增加一个节点都会在原有的节点中加入该节点的信息,如此类推,所以当节点数量过大时,所存储的信息也越多,所以一个集群最大连接为一千左右

索引数组可以保存所有的槽道管理者信息

初始化过程中,创建集群,每一个节点都会将所有集群的结点信息保存到内存的各个对象中,每一个对象都有集群节点的ip,port,id等等

三.Redis集群槽道原理

CLUSTER INFO 打印集群的信息
CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相关信息。 
//节点
CLUSTER MEET <ip> <port> 将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。
CLUSTER FORGET <node_id> 从集群中移除 node_id 指定的节点。
CLUSTER REPLICATE <node_id> 将当前节点设置为 node_id 指定的节点的从节点。
CLUSTER SAVECONFIG 将节点的配置文件保存到硬盘里面。
CLUSTER ADDSLOTS <slot> [slot ...] 将一个或多个槽(slot)指派(assign)给当前节点。
CLUSTER DELSLOTS <slot> [slot ...] 移除一个或多个槽对当前节点的指派。
CLUSTER FLUSHSLOTS 移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
CLUSTER SETSLOT <slot> NODE <node_id> 将槽 slot 指派给 node_id 指定的节点。
CLUSTER SETSLOT <slot> MIGRATING <node_id> 将本节点的槽 slot 迁移到 node_id 指定的节点中。
CLUSTER SETSLOT <slot> IMPORTING <node_id> 从 node_id 指定的节点中导入槽 slot 到本节点。
CLUSTER SETSLOT <slot> STABLE 取消对槽 slot 的导入(import)或者迁移(migrate)。 
//键
CLUSTER KEYSLOT <key> 计算键 key 应该被放置在哪个槽上。
CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的键值对数量。
CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 个 slot 槽中的键。 
//新增
CLUSTER SLAVES node-id 返回一个master节点的slaves 列表

四.调用集群命令cluster meet 节点碰撞

1.杀死所以进程,并且把生产的文档全部删除

2.启动对应的节点

3.启动完毕

4.节点握手

127是在本地登录的 无法跨服务握手,需要输入对应的IP 

5.握手测试

登录任何启动的节点; >cluster meet ip port(ip 端口是其他节点信息)

注意:跨服务器执行集群的搭建 bind127.0.0.1和网卡的ip地址,需要登录时使用对外访问ip地址;

6.全部加入进去  集群节点握手成功

目前集群创建成功但是,还是无法使用,因为没有分配槽道,无管理权

7.分配槽道

给8001分配 0 -1 槽道 

登录任何启动的节点; >cluster meet ip port(ip 端口是其他节点信息)

注意:跨服务器执行集群的搭建 bind127.0.0.1和网卡的ip地址,需要登录时使用对外访问ip地址;

8.写个脚本,循环分配槽道

编写成功,保存运行

编写成功运行时切记 {3..5461}没有空格!!我写错了没运行成功,我修改了文件

重新修改当前脚本,把其他节点的槽道分配

分配完成进入一个节点查看一下

9.在操作分配槽道的时候,如何初始化槽道 cluster addslots xxx

  • 分配对应的槽道二进制会改变
  • 其他未分配的槽道的二进制不会发生改变 
  • 数组会全部改变
  • 因为全部集群的数组是共享的,都会发生改变  内容是一致的

10.查看集群状态

11.添加从节点(默认添加的都是主节点)

进入要添加从节点中

输入要加入主节点的ID 我设置的是8001主节点的ID

总结:redis-trib.rb 命令文件,就是利用ruby语言完成上述步骤的封装;对外提供方便的调用命令;

12.槽道迁移(空槽道迁移)

案例:10923槽道迁移 原先在8003节点上,迁移到8002节点上    

1.首先登陆到8002上

后面的ID是要迁移槽道的原节点ID(8003) 正在显示

2.进入8003,进行导出

后面的ID是要迁移槽道的新节点ID(8002) 

  • 槽道的状态是正常,导入,导出,都不影响数据的插入
  • 数据微调的时候,集群不能对外提供服务;
  • 数据迁移工作,在维护内容属于重大维护事项;

4.通知所有集群过半主节点槽道迁移了(所有的节点,数组发生变化)

cluster setslot 10923 node 8002节点id 所有集群节点都执行这个操作

将所有集群节点通知到,10923从现在开始,归8002所有

13.非槽道迁移

由于搭建集群出错,我又重新搭建一个,按照我上面的步骤(sh recreate.sh),三分钟左右搭建完成、随意往一个主节点中输入一个值

查到我输入的值在8001节点中,

之前的两步跟上面一样,把含有数据的节点导入到8002中

将槽道的数据迁移到目标节点(登录源节点迁移数据) 槽道还是在8001节点中 

确定当前槽道包含的所有key(5798)

 "name"将获取的key值,进行迁移,从8001迁移到8002

8001>migrate 目标节点ip 目标端口 "" 0 500 keys name

migrate 10.42.60.249  8002  " " 0 500 keys key1 key2 ...

  • "": 表示key的匹配; 可以使用正则(有待考证)
  • 0: 表示迁移到目标节点的database(0-15)
  • 500:连接超时毫秒
  • keys:标签确定迁移的key值名称
  • name:key
  • 如果有多个key:keys name1 name2 name3 name4
  • 除了key-value执行迁移,map记录{槽道:[key集合]}的内容一并迁移

 

迁移成功

去8002查找发现,数据没有过来,直接跳回到8001,

因为槽道没有迁移,我们需要通知集群其他节点,5798迁移过去

这是就全部完成了  如果多个KEY 就在后面追加

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值