1.创建 redis cluster集群的环境准备
每个Redis 节点采用相同的相同的Redis版本、相同的密码、硬件配置
所有Redis服务器必须没有任何数据
准备六台主机,地址如下
10.0.0.8
10.0.0.18
10.0.0.28
10.0.0.38
10.0.0.48
10.0.0.58
2.启用 redis cluster 配置
6台机器安装好redis后,所有主机都执行以下配置
每个节点修改redis配置,必须开启cluster功能的参数
#如果是编译安装可以执行下面操作
[root@redis-node1 ~]#sed -i.bak -e '/masterauth/a masterauth 123456' -e '/# cluster-enabled yes/a cluster-enabled yes' -e '/# cluster-config-file nodes-6379.conf/a cluster-config-file nodes-6379.conf' -e '/cluster-requirefull-coverage yes/c cluster-require-full-coverage no' /apps/redis/etc/redis.conf
[root@redis-node1 ~]#systemctl enable --now redis
#也可以手动修改修改配置文件
[root@redis-node1 ~]vim /etc/redis.conf
bind 0.0.0.0
masterauth 123456 #建议配置,否则后期的master和slave主从复制无法成功,还需再配置
requirepass 123456
cluster-enabled yes #取消此行注释,必须开启集群,开启后 redis 进程会有cluster标识
cluster-config-file nodes-6379.conf #取消此行注释,此为集群状态数据文件,记录主从关系 及slot范围信息,由redis cluster 集群自动创建和维护
cluster-require-full-coverage no #默认值为yes,设为no可以防止一个节点不可用导致整 个cluster不可用
验证当前Redis服务状态:
#开启了16379的cluster的端口,实际的端口=redis port + 10000
[root@centos8 ~]#ss -ntl
#注意进程有[cluster]状态
[root@centos8 ~]#ps -ef|grep redis
3.创建集群
#命令redis-cli的选项 --cluster-replicas 1 表示每个master对应一个slave节点
[root@redis-node1 ~]#redis-cli -a 123456 --cluster create 10.0.0.8:6379 10.0.0.18:6379 10.0.0.28:6379 10.0.0.38:6379 10.0.0.48:6379 10.0.0.58:6379 --cluster-replicas 1
#观察以上结果,可以看到3组master/slave
master:10.0.0.8---slave:10.0.0.38
master:10.0.0.18---slave:10.0.0.48
master:10.0.0.28---slave:10.0.0.58
#如果节点少于3个会出下面提示错误
[root@node1 ~]#redis-cli -a 123456 --cluster create 10.0.0.8:6379 10.0.0.18:6379
4.验证集群
每个机器上都可以查看主从状态
[root@redis-node1 ~]#redis-cli -a 123456 -c INFO replication
查看指定master节点的slave节点信息
[root@centos8 ~]#redis-cli -a 123456 cluster nodes
验证集群状态
[root@redis-node1 ~]#redis-cli -a 123456 CLUSTER INFO
#查看任意节点的集群状态
[root@redis-node1 ~]#redis-cli -a 123456 --cluster info 10.0.0.38:6379
查看对应关系
[root@redis-node1 ~]#redis-cli -a 123456 CLUSTER NODES
[root@redis-node1 ~]#redis-cli -a 123456 --cluster check 10.0.0.38:6379
5.测试集群写入数据
redis cluster 写入key
#经过算法计算,当前key的槽位需要写入指定的node
[root@redis-node1 ~]#redis-cli -a 123456 -h 10.0.0.8 SET key1 values1
(error) MOVED 9189 10.0.0.18:6379 #槽位不在当前node所以无法写入
#指定槽位对应node可写入
[root@redis-node1 ~]#redis-cli -a 123456 -h 10.0.0.18 SET key1 values1
[root@redis-node1 ~]#redis-cli -a 123456 -h 10.0.0.18 GET key1
#对应的slave节点可以KEYS *,但GET key1失败,可以到master上执行GET key1
[root@redis-node1 ~]#redis-cli -a 123456 -h 10.0.0.48 KEYS "*"
[root@redis-node1 ~]#redis-cli -a 123456 -h 10.0.0.48 GET key1
redis cluster 计算key所属的slot
[root@centos8 ~]#redis-cli -h 10.0.0.8 -a 123456 --no-auth-warning cluster nodes
#计算得到hello对应的slot
[root@centos8 ~]#redis-cli -h 10.0.0.8 -a 123456 --no-auth-warning cluster keyslot hello
[root@centos8 ~]#redis-cli -h 10.0.0.8 -a 123456 --no-auth-warning set hello magedu
[root@centos8 ~]#redis-cli -h 10.0.0.8 -a 123456 --no-auth-warning cluster keyslot name
[root@centos8 ~]#redis-cli -h 10.0.0.8 -a 123456 --no-auth-warning set name wang
[root@centos8 ~]#redis-cli -h 10.0.0.18 -a 123456 --no-auth-warning set name wang
[root@centos8 ~]#redis-cli -h 10.0.0.18 -a 123456 --no-auth-warning get name "wang"
#使用选项-c 以集群模式连接
[root@centos8 ~]#redis-cli -c -h 10.0.0.8 -a 123456 --no-auth-warning
[root@centos8 ~]#redis-cli -h 10.0.0.28 -a 123456 --no-auth-warning get linux
6.python 程序实现Redis Cluster 访问
官网: github.com/Grokzen/red…
7.模拟故障实现故障转移
#模拟node2节点出故障,需要相应的数秒故障转移时间
[root@redis-node2 ~]#tail -f /var/log/redis/redis.log
[root@redis-node2 ~]#redis-cli -a 123456
[root@redis-node2 ~]# redis-cli -a 123456 --cluster info 10.0.0.8:6379
[root@redis-node2 ~]# redis-cli -a 123456 --cluster check 10.0.0.8:6379
[root@redis-node2 ~]#redis-cli -a 123456 -h 10.0.0.48
#恢复故障节点node2自动成为slave节点
[root@redis-node2 ~]#systemctl start redis
#查看自动生成的配置文件,可以查看node2自动成为slave节点
[root@redis-node2 ~]#cat /var/lib/redis/nodes-6379.conf
[root@redis-node2 ~]#redis-cli -a 123456 -h 10.0.0.48
8.集群扩容
扩容适用场景: 当前客户量激增,现有的Redis cluster架构已经无法满足越来越高的并发访问请求,为解决此问题,新购 置两台服务器,要求将其动态添加到现有集群,但不能影响业务的正常访问。
注意: 生产环境一般建议master节点为奇数个,比如:3,5,7,以防止脑裂现象
添加节点准备:增加Redis 新节点,需要与之前的Redis node版本和配置一致,然后分别再启动两台Redis node,应为一主一从。具体配置参考第二节。
添加新的master节点到集群
add-node new_host:new_port existing_host:existing_port [--slave --master-id ]
#说明:
new_host:new_port #指定新添加的主机的IP和端口
existing_host:existing_port #指定已有的集群中任意节点的IP和端口
Redis 5 以上版本的添加命令:
#将一台新的主机10.0.0.68加入集群,以下示例中10.0.0.58可以是任意存在的集群节点
[root@redis-node1 ~]#redis-cli -a 123456 --cluster add-node 10.0.0.68:6379 :6379
#观察到该节点已经加入成功,但此节点上没有slot位,也无从节点,而且新的节点是master
[root@redis-node1 ~]#redis-cli -a 123456 --cluster info 10.0.0.8:6379
[root@redis-node1 ~]#redis-cli -a 123456 --cluster check 10.0.0.8:6379
#和上面显示结果一样
[root@redis-node1 ~]#redis-cli -a 123456 CLUSTER NODES
#查看集群状态
[root@redis-node1 ~]#redis-cli -a 123456 CLUSTER INFO
在新的master上重新分配槽位
新的node节点加到集群之后,默认是master节点,但是没有slots,需要重新分配,否则没有槽位将无法访问
注意: 重新分配槽位需要清空数据,所以需要先备份数据,扩展后再恢复数据
Redis 5以上版本命令:
[root@redis-node1 ~]#redis-cli -a 123456 --cluster reshard :6379
How many slots do you want to move (from 1 to 16384)?4096 #新分配多少个槽位 =16384/master个数
What is the receiving node ID? d6e2eca6b338b717923f64866bd31d42e52edc98 #新的 master的ID
Source node #1: all #输入all,将哪些源主机的槽位分配给新的节点,all是自动在所有的redis node选择划分,如果是从redis cluster删除某个主机可以使用此方式将指定主机上的槽位全部移动到别的 redis主机
#确定slot分配成功
[root@redis-node1 ~]#redis-cli -a 123456 --cluster check 10.0.0.8:6379
为新的master指定新的slave节点
当前Redis集群中新的master节点存单点问题,还需要给其添加一个对应slave节点,实现高可用功能
在新加节点到集群时,直接将之设置为slave
Redis 5 以上版本添加命令:
redis-cli -a 123456 --cluster add-node 10.0.0.78:6379 :6379 -- cluster-slave --cluster-master-id d6e2eca6b338b717923f64866bd31d42e52edc98
9.集群缩容
缩容适用场景: 随着业务萎缩用户量下降明显,和领导商量决定将现有Redis集群的8台主机中下线两台主机挪做它用,缩容 后性能仍能满足当前业务需求
迁移要删除的master节点上面的槽位到其它master
注意: 被迁移Redis master源服务器必须保证没有数据,否则迁移报错并会被强制中断。
Redis 5版本以上命令
#查看当前状态
[root@redis-node1 ~]#redis-cli -a 123456 --cluster check 10.0.0.8:6379
#连接到任意集群节点,#最后1365个slot从10.0.0.8移动到第一个master节点10.0.0.28上
[root@redis-node1 ~]#redis-cli -a 123456 --cluster reshard 10.0.0.18:6379
How many slots do you want to move (from 1 to 16384)? 1356 #共4096/3分别给其它三个 master节点
What is the receiving node ID? d34da8666a6f587283a1c2fca5d13691407f9462 #master 10.0.0.28
Source node #1: cb028b83f9dc463d732f6e76ca6bbcd469d948a7 #输入要删除节点10.0.0.8的 ID Source node #2: done
#再将1365个slot从10.0.0.8移动到第二个master节点10.0.0.48上
[root@redis-node1 ~]#redis-cli -a 123456 --cluster reshard 10.0.0.18:6379 -- cluster-slots 1365 --cluster-from cb028b83f9dc463d732f6e76ca6bbcd469d948a7 -- cluster-to d04e524daec4d8e22bdada7f21a9487c2d3e1057 --cluster-yes
#最后的slot从10.0.0.8移动到第三个master节点10.0.0.68上
[root@redis-node1 ~]#redis-cli -a 123456 --cluster reshard 10.0.0.18:6379 -- cluster-slots 1375 --cluster-from cb028b83f9dc463d732f6e76ca6bbcd469d948a7 -- cluster-to d6e2eca6b338b717923f64866bd31d42e52edc98 --cluster-yes
#确认10.0.0.8的所有slot都移走了,上面的slave也自动删除,成为其它master的slave
[root@redis-node1 ~]#redis-cli -a 123456 --cluster check 10.0.0.8:6379
#原有的10.0.0.38自动成为10.0.0.68的slave
[root@redis-node1 ~]#redis-cli -a 123456 -h 10.0.0.68 INFO replication
从集群中删除服务器
上面步骤完成后,槽位已经迁移走,但是节点仍然还属于集群成员,因此还需从集群删除该节点
注意: 删除服务器前,必须清除主机上面的槽位,否则会删除主机失败
Redis 5以上版本命令:
[root@redis-node1 ~]#redis-cli -a 123456 --cluster del-node :6379 cb028b83f9dc463d732f6e76ca6bbcd469d948a7
#cb028b83f9dc463d732f6e76ca6bbcd469d948a7是删除节点的ID
#删除节点后,redis进程自动关闭
#删除节点信息
[root@redis-node1 ~]#rm -f /var/lib/redis/nodes-6379.conf
删除多余的slave节点验证结果
#验证删除成功
[root@redis-node1 ~]#ss -ntl
#删除多余的slave从节点
[root@redis-node1 ~]#redis-cli -a 123456 --cluster del-node 10.0.0.18:6379 f9adcfb8f5a037b257af35fa548a26ffbadc852d
#删除集群文件
[root@redis-node4 ~]#rm -f /var/lib/redis/nodes-6379.conf
#查看集群信息
[root@redis-node1 ~]#redis-cli -a 123456 -h 10.0.0.18 CLUSTER INFO
10.总结
Redis cluster 需要至少 3个master节点才能实现,slave节点数量不限,当然一般每个master都至少对应的 有一个slave节点
如果有三个主节点采用哈希槽 hash slot 的方式来分配16384个槽位 slot
此三个节点分别承担的slot 区间可以是如以下方式分配:节点M1 0-5460 ;节点M2 5461-10922 ;节点M3 10923-16383
集群扩容 当有新的节点准备好加入集群时,这个新的节点还是孤立节点,加入有两种方式。一个是通过集群节点 执行命令来和孤立节点握手,另一个则是使用脚本来添加节点。