redis迁移数据之槽道讨论

针对redis3.0之前的版本。在哨兵集群管理的主从结构的集群,结构如下

在这里插入图片描述

哨兵主从集群和三个单独redis节点的集群同时存在。

迁移数据; hash一致性,扩容时,迁移数据大量减少;
但是这种迁移是运维工程师做不了的,需要了解key值计算过程

当前结构的redis节点的利用率太低
真正接收数据做数据处理的节点,9个节点中,接收key值存储的只有3个

redis3.0版本之后,集群的结构如下:

在这里插入图片描述

  • 1 所有的redis节点彼此互联(包括所有的master和slave),使用内部的二进制协议优化传输文件,优化速度;

  • 2 节点的fail,选举等,通过集群中过半数量的主节点投票选举(将哨兵的逻辑和主节点整合)

  • 3 客户端jedis,连接集群不一定要连接主节点,不一定要连接所有的节点,只需要通过连接其中一部分就可以,jedis传递的key值可以在集群内部进行转发,数据分片由集群维护

  • 4 (与hash一致性不同)redis集群把所有的主节点映射,投放到了一个0-16383个槽道(slot)(不一定平均分配) key值与槽道进行计算连通(哈希取模运算,底层散列算法CRC16) 数据–>slot–>master node

  • 5 当数据将要存储到集群时,由于连接的未必是master,slave也可以接收数据,key值计算结果0-16383整数,集群中任何一个节点获取这个整数后,都配将key值发送到管理整数对应的槽道号的节点(主节点)进行存储,从节点没有管理槽道号的权利.

槽道号:
在这里插入图片描述

槽道号到底是什么?如何在集群中管理槽道的概念?

槽道引入后的好处:
可以单独处理当前集群的槽道管理
master01:0-5000
master02:5001-10000
master03:10001-16383

可以通过命令,重新划分槽道时候,key值也需要跟着槽道迁移
维护人员可以用redis命令完成的过程

槽道到底是什么?
1 节点在获取key值的时候如何判断当前key值对应的槽道号是否归我管理
2 当key值的槽道号不归当前节点管理时,当前节点如何知道正确的管理node

槽道的逻辑包含两个部分:
16384位的二进制位序列,16384个元素的共享数组

每个节点上都有以上两个数据,数组在集群的节点中内容完全一致,二进制16384位序列主节点完全不一致的,从节点都是0;

2 进制的位序列16384位(8位为例)
8位二进制位序列
在这里插入图片描述

当前节点的位序列中下标号(计算出来的)对应的二进制值如果是1,表示下标号同槽道号归当前节点管理,如果是0,不管理
上图的结果
8000节点管理的槽道:0,1,2
假设传递一个key=“name”–>slot num=4

所有的master都管理部分槽道号,二进制的位序列在所有master中的值都不一样,所有master的二进制做位的或运算=16384位个全是1的二进制,与预算=0

slave作为存储数据,但是不管理槽道的节点,二进制是0

cluster nodes 展示的10进制的槽道号管理显示,通过对二进制计算的结果

共享数组:所有集群节点都保存一个完全一致的数组
16384个元素;数组中的元素内容,保存着当前元素下标对应槽道号的管理者的信息;

在这里插入图片描述

当前节点判断key值的映射结果不归当前节点管理时,直接通过数据中获取正确ip+port,将key值转发出去;
登录的集群客户端调用cluster nodes方法查看到的槽道状态
->- migrating 导出

槽道如何迁移:

- 1.重新create(cluster meet,手动分配槽道)

节点握手(3个节点,8000.8001.8002)
将集群节点间的关系通过meet建立
登录8000需要使用127.0.0.1以外的ip

#redis-cli -h 106.75.85.179 -c -p 8000
8000>cluster meet 106.75.85.179 8001
[root@10-9-62-65 redis-3.2.11]# redis-cli -h 106.75.85.179 -c -p 8000
106.75.85.179:8000> cluster meet 106.75.85.179 8001
106.75.85.179:8000> cluster meet 106.75.85.179 8002

- 2 指定槽道号(5461 5462 5461)
o指定某个节点的单个槽道,0 分配给8000,
8000>cluster addslots 0 1
在这里插入图片描述

无需完成手动输入的5461个槽道分配
- 3 编写shell脚本

for i in {4..5460};do redis-cli -h 106.75.85.179 -c -p 8000 cluster addslots $i;done
for i in {5461..10922};do redis-cli -h 106.75.85.179 -c -p 8001 cluster addslots $i;done
for i in {10923..16383};do redis-cli -h 106.75.85.179 -c -p 8002 cluster addslots $i;done

直接运行提示
-bash: ./8000slots.sh: Permission denied
开启执行sh脚本的权限

#chmod 777 *.sh(chmod代表变更文件或者目录的操作权限,777表示所有用户可读可写可执行后面跟着的文件或文件夹)
#./8000slots.sh
#./8001slots.sh
#./8002slots.sh

- 4 槽道迁移(空槽道,非空槽道)

迁移1000号,源节点8000节点把1000导给目标8001节点
目标节点8001导入1000号槽道(数组对应元素中槽道状态发生变化)
8001>cluster setslot 1000 importing 源节点id(8000)
会将当前节点8001中数组元素对应的1000号槽道中的状态从正常变成importing(-<-)
源节点8000导出1000号槽道
8000>cluster setslot 1000 migrating 目标节点id
8000里面的数组发生变化,槽道状态从正常变成导出migrating(->-)

以上的两步操作,不影响数据正常的set和get

通知所有节点该槽道迁移()

8000>cluster setslot 1000 node 目标节点id
8000节点二进制变化(下标1000的二进制值从1变成0)
数组1000号下标的元素内容发生变化(从8000节点信息,导出状态,转化成8001节点信息,正常状态)
8001>cluster setslot 1000 node 目标节点id
8001的二进制,1000号下标的二进制值从0变成1,数组变化成自己的节点信息,槽道状态正常
8002>cluster setslot 1000 node 目标节点id

- 5 非空槽道迁移(说明槽道已经挂钩某一批key值,微调)

8000>set name xiaolaoshi
127.0.0.1:8002> set name xiaolaosih
-> Redirected to slot [5798] located at 106.75.85.179:8001
OK

- 6 迁移带有数据的槽道5798(在8001节点),迁移到8002
目标节点导入槽道

127.0.0.1:8002> cluster setslot 5798 importing 47dde9109e8a4ddfa6e9793b8c1029c48dbdc4a1
OK

源节点导出槽道

106.75.85.179:8001> cluster setslot 5798 migrating c698022f3bed60d18433a9adf0bd7c4df7dc2e79
OK

将5798的数据从源节点迁移到目标节点
确定当前槽道的所有key值

8001>cluster getkeysinslot 5798 100(查看5798上100范围的key)
"name"
omget不知道集群和分布式的,只能在一个节点上完成获取key的任务
8001>mget name

- 7 迁移数据 name

migrate 106.75.85.179 8002 "name" 0 500 

“”:表示多个key进行迁移,后面紧跟着所有key的值
“name”:单个key值迁移,需要在字符串中添加key值

106.75.85.179:8001> migrate 106.75.85.179 8002 "name" 0 500 
OK

查看是否从8001迁移成功,mget name

127.0.0.1:8001> get name
(error) ASK 5798 106.75.85.179:8002
从8001迁移到8002 登录8001执行
8001>migrate 目标节点ip 目标节点端口

- 8 通知所有节点槽道迁移

8000> cluster setslot 5798 node 目标节点id
8001> cluster setslot 5798 node 目标节点id
8002> cluster setslot 5798 node 目标节点id

- 9 将剩下的三个节点8003.8004.8005分别对应一个主节点添加从节点**
先将8003,04,05 与集群握手

8000>cluster meet ip port
8003>cluster replicate master-id

- 10 最终的集群的结构
3个主节点,对应各自一个从节点
在这里插入图片描述

脚本文件如下:

8000slots

for i in {4..5460};do redis-cli -h 106.75.85.179 -c -p 8000 cluster addslots $i;done

8001slots

for i in {5461..10922};do redis-cli -h 106.75.85.179 -c -p 8001 cluster addslots $i;done

8002slots

for i in {10923..16383};do redis-cli -h 106.75.85.179 -c -p 8002 cluster addslots $i;done

总结:

redis3.0引入了redis集群

  • 1 所有的redis节点彼此互联(包括所有的master和slave),使用内部的二进制协议优化传输文件,优化速度;
  • 2 节点的fail,选举等,通过集群中过半数量的主节点投票选举(将哨兵的逻辑和主节点整合)
  • 3 客户端jedis,连接集群不一定要连接主节点,不一定要连接所有的节点,只需要通过连接其中一部分就可以,jedis传递的key值可以在集群内部进行转发,数据分片由集群维护
  • 4 (与hash一致性不同)redis集群把所有的主节点管理若干个0-16383个槽道(slot)(不一定平均分配) key值与槽道进行计算连通(哈希取模运算,底层散列算法CRC16) 数据–>slot–>master node
    创建完集群后,启动了一个8001客户端,set name xiao,
    没有为8001分配槽道的情况下,存储失败
  • 5 当数据将要存储到集群时,由于连接的未必是master,slave也可以接收数据,key值计算结果0-16383整数,集群中任何一个节点获取这个整数后,都配将key值发送到管理整数对应的槽道号的节点(主节点)进行存储,从节点没有管理槽道号的权利,
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值