阿昌在这里总结记录一下,如何通过docker搭建redis哈希槽分区解决方案
的集群【3主3从
】
涉及知识:
- redis
- docker基本指令
- linux
- 哈希槽分区
二、理论
在开始搭建之前搭建需要知道3种在redis集群搭建的分区算法,分别为:哈希取余分区
、一致性哈希算法分区
、哈希槽分区
1、哈希取余分区
- 描述图
介绍
通过对key取余来直接确定他存放或读取拿个redis。
2亿条记录就是2亿个k,v,我们单机不行必须要分布式多机,假设有3台机器构成一个集群,用户每次读写操作都是根据公式:
hash(key) % N个机器台数
,计算出哈希值,用来决定数据映射到哪一个节点上。优点
简单粗暴
,直接有效,只需要预估好数据规划好节点。例如3台、8台、10台,就能保证一段时间的数据支撑。使用Hash算法让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求(并维护这些请求的信息),起到
负载均衡
+分而治之
的作用。缺点
原来规划好的节点,进行扩容或者缩容就比较麻烦
。不管扩缩,每次数据变动导致节点有变动,映射关系需要重新进行计算,在服务器个数固定不变时没有问题,如果需要弹性扩容或故障停机的情况下,原来的取模公式就会发生变化:Hash(key)/3会变成Hash(key) /?。此时地址经过取余运算的结果将发生很大变化,根据公式获取的服务器也会变得不可控。 某个redis机器宕机了,由于台数数量变化,会导致hash取余全部数据重新洗牌。
2、一致性哈希算法分区
描述图
介绍
分布式缓存数据变动和映射问题,某个机器宕机了,分母数量改变了,自然取余数不OK了。
目的
为了在节点数目发生改变时尽可能少的迁移数据
将所有的存储节点排列在收尾相接的Hash环上,每个key在计算Hash后会
顺时针
找到临近的存储节点存放。而当有节点加入或退出时仅影响该节点在
Hash环上顺时针相邻的后续节点
。优点
- 一致性哈希算法的
容错性
- 一致性哈希算法的
扩展性
- 一致性哈希算法的
缺点
- 当节点数量少时,会出现一致性哈希算法的
数据倾斜
问题
- 当节点数量少时,会出现一致性哈希算法的
3、哈希槽分区
描述图
介绍
根据上面的
一致性哈希算法分区
再进一步衍生出哈希槽分区
,分为哈希槽,其实质就是一个数组,数组[0,2^14 -1]形成hash slot空间。一个集群只能有16384个槽
,编号0-16383(0-2^14-1)。这些槽会分配给集群中的所有主节点,分配策略没有要求。可以指定哪些编号的槽分配给哪个主节点。集群会记录节点和槽的对应关系。解决了节点和槽的关系后,接下来就需要对key求哈希值,然后对16384取余,余数是几key就落入对应的槽里。slot = CRC16(key) % 16384
。以槽为单位移动数据,因为槽的数目是固定的,处理起来比较容易,这样数据移动问题就解决了。目的
解决均匀分配的问题,
在数据和节点之间又加入了一层,把这层称为哈希槽(slot),用于管理数据和节点之间的关系
,现在就相当于节点上放的是槽,槽里放的是数据。【有点像将数组的一个一个位置反向代理成一个操作
】槽解决的是粒度问题,相当于把粒度变大了,这样便于
数据移动
。哈希解决的是映射问题,使用key的哈希值来计算所在的槽,便于
数据分配
。
那这里理论就结束了,下面我就用docker搭建对应的Redis集群。
三、3主3从Redis集群搭建
1、确保Docker服务启动
1 | systemctl start docker |
2、新建6个docker容器redis实例
- docker命令
1 | 节点-1 |
- 指令说明
docker run
:创建并运行docker容器实例--name redis-node-6
:容器名字--net host
:使用宿主机的IP和端口,默认--privileged=true
:获取宿主机root用户权限-v /data/redis/share/redis-node-6:/data
:容器卷,宿主机地址:docker内部地址redis:6.0.8
:redis镜像和版本号--cluster-enabled yes
:开启redis集群--appendonly yes
:开启aof持久化--port 6386
:redis端口号
3、构建集群关系
- 进入容器—这里以node1为例
1 | docker exec -it redis-node-1 /bin/bash |
- 构建关系
注意,进入docker容器后才能执行一下命令,且注意自己的真实IP
地址,阿昌这里是ip为:192.168.88.128
1 | redis-cli --cluster create 192.168.88.128:6381 192.168.88.128:6382 192.168.88.128:6383 192.168.88.128:6384 192.168.88.128:6385 192.168.88.128:6386 --cluster-replicas 1 |
4、查看集群状态
- 查看集群状态—这里以node-1,6381作为切入点
1 | redis-cli -p 6381 cluster info |
- 查看集群节点
1 | redis-cli -p 6381 cluster nodes |
5、集群的读写存储
- 通过
-c
参数实现读写存储切换集群节点
因为他在读写key的时候会对key进行计算出这个key所在哪个节点的槽位,每个操作都对应每个节点才可以去读写
1 | redis-cli -p 6381 -c |
6、查看集群信息
1 | redis-cli --cluster check 192.168.88.128:6382 |
7、关于容错切换迁移
如果我们node1节点宕机了,那他的从节点就会顶上作为新的Master。如果node1节点后续又王者回归后,他也只能重新做新Master的从节点。
在我们这里的情况node-1节点的从节点是node-6,所以当node-1宕机后,node6就会成为新的master。
四、主从扩容
1、创建要扩容的节点
这里我们以再加入一对主从节点6387、6388,且6387是主,6388是从
1 | 节点-7,主节点 |
2、进入6387容器实例内部
1 | docker exec -it redis-node-7 /bin/bash |
3、将新增的6387节点(空槽号)作为master节点加入原集群
新增节点到集群中
将新增的6387作为master节点加入集群
1
2
3redis-cli --cluster add-node 192.168.88.128:6387 192.168.88.128:6381
6387 就是将要作为master新增节点
6381 就是原来集群节点里面的领路人,相当于6387拜拜6381的码头从而找到组织加入集群检查集群情况第1次
1
redis-cli --cluster check 192.168.88.128:6381
重新分派槽号—reshard
1
redis-cli --cluster reshard 192.168.88.128:6381
- 指定再分配的节点槽位数量
4096
—–16384/4
指定要给“谁”,是新机器node7
指定来源,是
所有节点
—all
是否继续分配—yes
- 指定再分配的节点槽位数量
查看分配槽位后的结果
1 | redis-cli --cluster check 192.168.88.128:6381 |
上面的node-7节点再分配到的操作发现是
[0-1364],[5461-6826],[10923-12287]
结论是:他是将之前3个槽位的节点,
大家都抠出来一点
再分配给新节点node-7
4、将node-8从节点加入Redis集群
1 | redis-cli --cluster add-node 192.168.88.128:6388 192.168.88.128:6387 --cluster-slave --cluster-master-id 258cb3004944d0d80ac32c501d2c4d6094f5ced3 |
5、再次检查集群情况
1 | redis-cli --cluster check 192.168.88.128:6382 |
此时就有4台节点,且node-7是主节点,node-8是node-7的从节点。
那到这里主从扩容就结束了!
五、主从缩容
1、说明
将6387和6388下线,如果要删除一对主从,就需要先下线6388节点
,再下线6387节点
2、检查集群情况1获得6388的节点ID
1 | redis-cli --cluster check 192.168.88.128:6382 |
3、将集群中将从节点6388删除
1 | redis-cli --cluster del-node 192.168.88.128:6388 861e143b54b5dff826964ccb9b0ab6a4be6dddcf |
4、检查集群节点状态
1 | redis-cli --cluster check 192.168.88.128:6382 |
5、将6387的槽号清空,重新分配,本例将清出来的槽号都给6381
1 | redis-cli --cluster reshard 192.168.88.128:6381 |
6、检查集群情况
1 | redis-cli --cluster check 192.168.88.128:6382 |
7、将6387删除
1 | redis-cli --cluster del-node 192.168.88.128:6387 258cb3004944d0d80ac32c501d2c4d6094f5ced3 |
8、检查集群情况
1 | redis-cli --cluster check 192.168.88.128:6382 |
此时就删除了一对主从6387和6388节点
这就是本次记录分享的内容,感谢你能看到这里 (๑′ㅂ`๑)!!!