redis集群(去中心化)原理+配置集群+集群扩容、缩容完整实验流程
1.redis集群原理
redis的集群模式通过数据的分布式存储实现去中心化的思想。redis通过对数据进行分片,将不同的数据存储在不同的master节点上面,从而解决了海量数据的存储问题。redis也内置了高可用机制,支持N个master节点,每个master节点都可以挂载多个slave节点,当master节点挂掉时,集群会提升它的某个slave节点作为新的master节点。
在集群创建的时候为每个节点添加一个从节点A1、B1、C1,那么整个集群便有三个master节点和三个slave节点(从节点必须为单数)组成,这样在节点B失败后,集群便会选举B1为新的主节点继续服务,整个集群便不会因为槽找不到而不可用了。但当B和B1都失败后,集群是不可用的。
redis集群引入了哈希槽slots实现数据的分布式存储;redis集群有16384个哈希槽,在redis数据库中进行键值插入修改时,每个key通过CRC16校验后对16384取模来决定放置哪个槽(slot = CRC16(key)%16384),集群的每个节点负责一部分hash槽。
2.配置集群
需要准备6台服务器,但是由于本电脑内存不足,可以准备三台服务器,这三台服务器首先都为master,端口为6379;再在各个服务器上将配置文件复制一份,重新分个端口号6380即可,那么三台从slave也就准备好了。
注意:redis集群中,系统会自动给三台主master分配从服务器,并不是slave1就是master1的从服务器,也可能是master2或master3的。
因此,本次使用三台服务器,每台服务器上运行一主一从。
2.1环境说明
2.2定位master1
#编辑配置文件
[root@redis-master1 ~]# vim /etc/redis/redis.conf
port 6379 #修改端口号
pidfile /var/run/redis_6379.pid #修改pid文件名
dir /var/lib/redis #持久化文件存放目录
dbfilename dump_6379.rdb #修改持久化文件名
bind 0.0.0.0 #绑定地址,允许任何ip访问
daemonize yes #让redis后台运行
protected-mode no #关闭保护模式
logfile /var/log/redis/redis_6379.log #指定日志
cluster-enabled yes # 开启集群功能
cluster-config-file nodes-6379.conf #设定节点配置文件名,不需要我们创建,由redis自己维护
cluster-node-timeout 10000 #节点心跳失败的超时时间,超过该时间(毫秒),集群自动进行主从切换
[root@redis-master1 ~]# systemctl restart redis #启动redis#启动6380端口的redis
[root@redis-master1 ~]# cp /etc/redis/redis.conf /etc/redis/redis-6380.conf #复制配置文件为端口号为6380的配置文件
[root@redis-master ~]# sed -i 's/6379/6380/g' /etc/redis/redis-6380.conf #将其中的6379改为6380
[root@redis-master ~]# cat /etc/redis/redis-6380.conf
bind 0.0.0.0
protected-mode no
port 6380
daemonize no
pidfile /var/run/redis_6380.pid
logfile /var/log/redis/redis_6380.log
dbfilename dump_6380.rdb
dir /var/lib/redis
cluster-enabled yes
cluster-config-file nodes-6380.conf
cluster-node-timeout 15000
[root@redis-master1 ~]# grep '6380' /etc/redis/redis-6380.conf #过滤查看
# Accept connections on the specified port, default is 6380 (IANA #815344).
port 6380
# tls-port 6380
pidfile /var/run/redis_6380.pid
logfile /var/log/redis/redis_6380.log
dbfilename dump_6380.rdb
cluster-config-file nodes-6380.conf
# cluster-announce-tls-port 6380
# cluster-announce-bus-port 6380
[root@redis-master1 ~]# redis-server /etc/redis/redis-6380.conf #启动6380端口的配置脚本
[root@redis-master1 ~]# ss -lntup | grep redis #查看是否有两个redis实例,分别存在6379和6380端口的redis服务#将配置文件复制到两外两台master主机依次启动
[root@redis-master1 ~]# scp /etc/redis/redis.conf /etc/redis/redis-6380.conf root@192.168.31.200:/etc/redis
[root@redis-master1 ~]# scp /etc/redis/redis.conf /etc/redis/redis-6380.conf root@192.168.31.210:/etc/redis
2.3定位master2
[root@redis-master2 ~]# systemctl restart redis
[root@redis-master2 ~]# redis-server /etc/redis/redis-6380.conf
[root@redis-master2 ~]# ss -lntup | grep redis #两个redis都已运行
2.4定位master3
[root@redis-master3 ~]# systemctl restart redis
[root@redis-master3 ~]# redis-server /etc/redis/redis-6380.conf
[root@redis-master3 ~]# ss -lntup | grep redis #两个redis都已运行
此时redis已经全部启动完成,接下来把 6 个服务器按预先规划的结构来组合成集群
2.5创建集群
#定位master1创建集群
[root@redis-master1 ~]# redis-cli --cluster create --cluster-replicas 1 192.168.31.100:6379 192.168.31.200:6379 192.168.31.210:6379 192.168.31.100:6380 192.168.31.200:6380 192.168.31.210:6380 #前三个为master的ip,后三个为slave的ip
#查看集群状态
[root@redis-master1 ~]# redis-cli -p 6379 cluster nodes
2.6测试
#连接集群存储数据
[root@redis-master1 ~]# redis-cli -p 6379 -c #加-c表示启用集群模式
127.0.0.1:6379> set cluster 3
-> Redirected to slot [14041] located at 192.168.31.210:6379
OK
192.168.31.210:6379> get cluster
"3"
#查看集群信息
192.168.31.210:6379> cluster nodes
3.故障转移
#定位master1;模拟master1宕机
[root@redis-master1 ~]# redis-cli -p 6379
127.0.0.1:6379> shutdown
not connected> exit
[root@redis-master ~]# redis-cli -p 6380
127.0.0.1:6380> cluster nodes ##可以看到master从100:6379切换到了200:6380#再次启动master1,可以发现master1变成了从
[root@redis-master ~]# systemctl start redis
[root@redis-master ~]# redis-cli -p 6379
127.0.0.1:6379> cluster nodes #master1变成了从
4.集群扩容
现在向集群中添加两个节点,这两个节点做一主一从。主节点的端口号为6381,从节点的端口号为6382。
4.1复制配置文件分配端口号
[root@redis-master1 ~]# cp /etc/redis/redis.conf /etc/redis/redis-6381.conf
[root@redis-master1 ~]# cp /etc/redis/redis.conf /etc/redis/redis-6382.conf
[root@redis-master1 ~]# sed -i 's/6379/6381/g' /etc/redis/redis-6381.conf
[root@redis-master1 ~]# sed -i 's/6379/6382/g' /etc/redis/redis-6382.conf
[root@redis-master ~]# grep '6381' /etc/redis/redis-6381.conf
[root@redis-master ~]# grep '6382' /etc/redis/redis-6382.conf
4.2添加节点到集群
#添加主节点
[root@redis-master ~]# redis-cli --cluster add-node 192.168.31.100:6381 192.168.31.200:6379 #添加31.100:6381到集群中,可以写任一主机master的地址:端口#添加从节点
#首先需要查看6381节点的ID值
[root@redis-master ~]# redis-cli -p 6381
127.0.0.1:6379> cluster nodes
[root@redis-master ~]# redis-cli --cluster add-node 192.168.31.100:6382 192.168.31.200:6379 --cluster-slave 801721f2fa2ec1005384fe5df0dec0e12072c42e #将100:6382以slave的身份加入192.168.31.200:6379所在集群,可以写集群中的任一主机ip:端口即可。id为100:6380的id
4.3分配插槽
#集群中增加了新节点,需要对现有数据重新进行分片操作
#定位master1
[root@redis-master1 ~]# redis-cli --cluster reshard 192.168.31.200:6379 --cluster-from fcac2c6fceea222bebb87e7ebd803d800a0a6e58 --cluster-to 801721f2fa2ec1005384fe5df0dec0e12072c42e --cluster-slots 100 --cluster-yes --cluster-timeout 5000 --cluster-pipeline 10 --cluster-replace
--cluster-slots 100:分配100个插槽
192.168.31.200:6379 集群内的任意一个主机ip:端口
--cluster-from fcac2c6fceea222bebb87e7ebd803d800a0a6e58 从集群内的任意一个主机的id来
--cluster-to 801721f2fa2ec1005384fe5df0dec0e12072c42e 到100:6381master的id去#查看插槽分配情况
[root@redis-master1 ~]# redis-cli -p 6379
127.0.0.1:6379> cluster nodes
5.集群缩容
添加节点的时候是先添加node节点到集群,然后分配槽位,删除节点的操作与添加节点的操作正好相反,是先将被删除的Redis node上的槽位迁移到集群中的其他Redis node节点上,然后再将其删除,如果一个Redis node节点上的槽位没有被完全迁移,删除该node的时候会提示有数据且无法删除。
#查看要被迁移的节点上有多少插槽
[root@redis-master1 ~]# redis-cli --cluster check
#缩容
[root@redis-master1 ~]# redis-cli --cluster reshard 192.168.31.200:6379 --cluster-from 801721f2fa2ec1005384fe5df0dec0e12072c42e --cluster-to fcac2c6fceea222bebb87e7ebd803d800a0a6e58 --cluster-slots 100--cluster-from 801721f2fa2ec1005384fe5df0dec0e12072c42e 100:6381master的id
--cluster-to fcac2c6fceea222bebb87e7ebd803d800a0a6e58 给集群内任意一个master的id