目录
一. 原理简述
二. 集群配置
2.1 环境准备
2.2 编译安装一个redis
2.3 创建集群
2.4 写入数据测试
实验一:
实验二:
实验三:
实验四:
添加节点
自动分配槽位
提升节点为master:
实验五:
实验六:
实验七:
官网文档(Redis集群规范) Redis cluster specification | Docs
一. 原理简述
此处的集群指的是Cluster, 通过分区/分片来实现一定程度的分布式与高可用部署。
二. 集群配置
Redis 最小集群规划,需要包含至少三个主节点,此处测试部署具有三个主服务器和三个从服务器的六节点群集。计划是在一台机器上模拟一个集群,主节点端口为三个, 从节点三个,这和生产环境的集群搭建没本质区别。下面的配置就将创建的六个redis实例端口修改为7001,7002,7003,7004,7005,7006,每个虚拟机中部署两个redis实例。
命令 | 含义 |
---|---|
cluster info | 获取集群的状态信息,包括插槽状态、节点数量等。 |
cluster nodes | 获取集群中所有节点的详细信息,包括节点ID、角色、状态等。 |
cluster meet <ip> <port> | 将新的节点加入到集群中。 |
cluster addslots <slot> | 为当前节点分配一个或多个插槽。 |
cluster delslots <slot> | 从当前节点删除一个或多个插槽。 |
cluster setslot <slot> <node-id> | 将一个插槽分配给指定节点。 |
cluster replicate <node-id> | 将当前节点设置为目标节点的从节点。 |
cluster failover | 触发趋向安全的故障转移,将当前从节点提升为主节点。 |
cluster reset | 重置集群状态(谨慎使用),可以选择温和模式或硬重置模式。CLUSTER RESET 命令可以选择温和模式(soft reset)或硬重置模式(hard reset)。温和模式通常只清除槽位信息而不改变节点ID,而硬重置模式则会生成新的节点ID。默认为温和重置模式。 |
cluster saveconfig | 将当前集群配置数据保存到集群节点的配置文件中。 |
cluster replicas <node-id> | 列出指定主节点的所有从节点。 |
cluster myid | 获取当前节点的ID。 |
cluster slots | 获取集群中所有插槽的分布情况。 |
cluster flushslots | 清空当前节点的所有插槽信息。 |
cluster keyslot <key> | 根据给定的键值计算出其对应的插槽。 |
删除节点的步骤
步骤 | 命令 | 含义 |
---|---|---|
数据迁移 | redis-cli --cluster reshard --cluster-from <源节点ID> --cluster-to <目标节点ID> --cluster-slots <迁移插槽数> -h <集群中的任一节点IP> -p <端口> 或 手动使用cluster setslot 命令 | 将待删除节点的数据迁移到其他节点(可以手动也可自动)。 |
节点删除 | redis-cli -h <其他节点IP> -p <其他节点端口> cluster forget <节点ID> | 通知集群中的其他节点忘记被删除的节点。 |
节点下线(可选) | redis-cli -h <节点IP> -p <节点端口> shutdown | 关闭被删除节点的Redis服务器实例。 |
2.1 环境准备
localhost | rocky_linux9.4 | 192.168.226.21 | redis5.0.10 |
localhost | rocky_linux9.4 | 192.168.226.22 | redis5.0.10 |
localhost | rocky_linux9.4 | 192.168.226.23 | redis5.0.10 |
关闭防火墙和selinux,时间同步。
2.2 编译安装一个redis
现在选择第一台192.168.226.21进行先编译安装一个redis,步骤如下
[root@localhost ~]# wget http://download.redis.io/releases/redis-5.0.10.tar.gz #下载redis
[root@localhost ~]# tar xzf redis-5.0.10.tar.gz -C /usr/local #解压
[root@localhost ~]# cd /usr/local/
[root@localhost local]# mv redis-5.0.10/ redis7001
[root@localhost local]# cd redis7001/
[root@localhost redis]# yum install -y gcc make #安装编译工具
[root@localhost redis]# make
注:如果报错请将刚才解压的安装包删除掉,再次重新解压并进行make安装即可。
#以下为定义参数
#创建持久化数据目录
[root@localhost ~]# mkdir /usr/local/redis7001/data
[root@localhost ~]# cd /usr/local/redis7001
[root@localhost redis7001]# cp redis.conf redis.conf.bak #备份配置文件
[root@localhost redis7001]# vim redis.conf #在配置文件中找到修改如下
bind 0.0.0.0 #默认ip为127.0.0.1 需要改为其他节点机器可访问的ip 否则创建集群时无法访问对应的端口,无法创建集群
pidfile /var/run/redis_7001.pid #pidfile文件对应7001,7002,7003,7004,7005,7006
dir /usr/local/redis7001/data/ #数据文件存放位置对应7001,7002,7003,7004,7005,7006
port 7001 #端口7001
timeout 300
daemonize yes #redis后台运行
pidfile "/var/log/redis7001.log" #日志目录
cluster-enabled yes #开启集群
cluster-config-file nodes-7001.conf #集群配置信息,开启集群后自动生成
cluster-node-timeout 5000 #请求超时时长
appendonly yes #开启aof日志,它会每次写操作都记录一条日志
[root@localhost redis7001]# cd
#拷贝五个redis实例,每个虚拟里放两个redis实例
[root@localhost ~]# cd ~ && cp -r /usr/local/redis7001 /usr/local/redis7002
[root@localhost ~]# scp -r /usr/local/redis7001 root@192.168.226.22:/usr/local/redis7003
[root@localhost ~]# scp -r /usr/local/redis7001 root@192.168.226.22:/usr/local/redis7004
[root@localhost ~]# scp -r /usr/local/redis7001 root@192.168.226.23:/usr/local/redis7005
[root@localhost ~]# scp -r /usr/local/redis7001 root@192.168.226.23:/usr/local/redis7006
#修改剩下五个实例中的7001为自己对应的号
[root@localhost ~]# vim /usr/local/redis7002/redis.conf
#在配置未见中使用语法 :%s/7001/7002/g 即可快速匹配替换,然后保存退出
#在另外两个主机中,对剩下的四个redis实例用也同样的方法去快速匹配修改,注意在命令中修改数字,这里不在赘述
启动六个redis实例,并查验端口是否正常
#对192.168.226.21操作
[root@localhost ~]# /usr/local/redis7001/src/redis-server /usr/local/redis7001/redis.conf
[root@localhost ~]# /usr/local/redis7001/src/redis-server /usr/local/redis7002/redis.conf
[root@localhost ~]# ss -tnlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 0.0.0.0:17001 0.0.0.0:* users:(("redis-server",pid=7908,fd=9))
LISTEN 0 511 0.0.0.0:17002 0.0.0.0:* users:(("redis-server",pid=7914,fd=9))
LISTEN 0 511 0.0.0.0:7001 0.0.0.0:* users:(("redis-server",pid=7908,fd=6))
LISTEN 0 511 0.0.0.0:7002 0.0.0.0:* users:(("redis-server",pid=7914,fd=6))
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=854,fd=3))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=854,fd=4))
#对192.168.226.22操作
[root@localhost local]# /usr/local/redis7003/src/redis-server /usr/local/redis7003/redis.conf
[root@localhost local]# /usr/local/redis7003/src/redis-server /usr/local/redis7004/redis.conf
[root@localhost local]# ss -tnlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 0.0.0.0:7004 0.0.0.0:* users:(("redis-server",pid=10220,fd=6))
LISTEN 0 511 0.0.0.0:7003 0.0.0.0:* users:(("redis-server",pid=10215,fd=6))
LISTEN 0 511 0.0.0.0:17004 0.0.0.0:* users:(("redis-server",pid=10220,fd=9))
LISTEN 0 511 0.0.0.0:17003 0.0.0.0:* users:(("redis-server",pid=5693,fd=6))
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=859,fd=3))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=859,fd=4))
#对192.168.226.23操作
[root@localhost ~]# /usr/local/redis7005/src/redis-server /usr/local/redis7005/redis.conf
[root@localhost ~]# /usr/local/redis7006/src/redis-server /usr/local/redis7006/redis.conf
[root@localhost ~]# ss -tnlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 0.0.0.0:17006 0.0.0.0:* users:(("redis-server",pid=1783,fd=9))
LISTEN 0 511 0.0.0.0:17005 0.0.0.0:* users:(("redis-server",pid=1778,fd=9))
LISTEN 0 511 0.0.0.0:7006 0.0.0.0:* users:(("redis-server",pid=1783,fd=6))
LISTEN 0 511 0.0.0.0:7005 0.0.0.0:* users:(("redis-server",pid=1778,fd=6))
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=858,fd=3))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=858,fd=4))
#上面启动命令中,有些前面的对应的数字没修改成对应数字是可以的,但是后面那个必须要对号才行。
2.3 创建集群
# 注意ip和端口的对应,这里用第一个,即7001的redis实例创建,如果换机器注意修改数字,--cluster-replicas 1是指定每个主节点有一个从节点
[root@localhost ~]# /usr/local/redis7001/src/redis-cli --cluster create --cluster-replicas 1 192.168.226.21:7001 192.168.226.21:7002 192.168.226.22:7003 192.168.226.22:7004 192.168.226.23:7005 192.168.226.23:7006
启动后接下开会有提示,对照后输入yes即可,这里一定要输入的是yes,不能是简写y,如下图:
创建完成后,验证集群状态:
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.21 -p 7001 cluster info
cluster_state:ok #表示集群状态是正常的
cluster_slots_assigned:16384 #表示集群中的插槽已分配的数量是16384,这是Redis集群的最大插槽数量。
cluster_slots_ok:16384 #表示集群中的插槽正常的数量是16384。
cluster_slots_pfail:0 #表示在插槽中标记为疑似故障(pfail)的节点数量是0。
cluster_slots_fail:0 #表示在插槽中标记为故障(fail)的节点数量是0。
cluster_known_nodes:6 #表示集群中已知节点的总数是6。
cluster_size:3 #表示集群的大小(即主节点的数量)是3。
cluster_current_epoch:6 #集群当前的配置版本(或配置纪元)。
cluster_my_epoch:1 #该节点最后一次选举的配置版本。
cluster_stats_messages_ping_sent:362 #此节点发送的ping消息数量。
cluster_stats_messages_pong_sent:331 #此节点发送的pong消息数量。
cluster_stats_messages_sent:693 #此节点发送的总消息数量。
cluster_stats_messages_ping_received:326 #此节点接收的ping消息数量。
cluster_stats_messages_pong_received:362 #此节点接收的pong消息数量。
cluster_stats_messages_meet_received:5 #此节点接收的meet消息数量。
cluster_stats_messages_received:693 #此节点接收的总消息数量。
ping:这是一个节点向其他节点发送的消息,用于检查其他节点的健康状态。当一个节点发送ping消息后,如果目标节点是活动的,它会回复一个pong消息。
pong:这是一个节点在收到其他节点的ping消息后发送的响应消息。它是对ping消息的响应,表示该节点当前是活动的。
meet:这是一种特殊类型的消息,当一个节点想要加入到集群中时会发送此消息。当一个节点收到meet消息后,它会将这个新节点添加到它所知道的节点列表中,并将这个信息通过ping消息传播给其他节点,以此方式把新节点引入到集群网络中。
使用以下命令查看集群中每个节点的状态 (当前登录的会在里面用myself标识出来,本下面第五行就标识出来了)
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.21 -p 7001 cluster nodes
870ed4837bcfc5d8e455c04ff4e2ec39156a652b 192.168.226.21:7002@17002 slave b0dc2767920f8e319e59709a88252cd46cfdda6d 0 1719391362667 5 connected
852c2c534e007a5155f96fba95c8333e334a5c3e 192.168.226.22:7004@17004 slave e4264f2bfaff2546625b9a8f559a0e822c5e24e1 0 1719391363820 4 connected
4cad4eebb85a849614ecaffeeb4b73da032fd974 192.168.226.22:7003@17003 master - 0 1719391362773 3 connected 5461-10922
e4264f2bfaff2546625b9a8f559a0e822c5e24e1 192.168.226.21:7001@17001 myself,master - 0 1719391359000 1 connected 0-5460
171b2751e63e86aa5335c149804a0e435dbb6f7f 192.168.226.23:7006@17006 slave 4cad4eebb85a849614ecaffeeb4b73da032fd974 0 1719391364235 6 connected
b0dc2767920f8e319e59709a88252cd46cfdda6d 192.168.226.23:7005@17005 master - 0 1719391363503 5 connected 10923-16383
2.4 写入数据测试
实验一:
使用当前主机节点连接别的主机节点,插入数据测试,提示失败
#不适用-c参数连接一个节点,结果不然插入数据,对应的哈希槽不匹配
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.23 -p 7006
192.168.226.23:7006> keys *
(empty list or set)
192.168.226.23:7006> set name zhangsan
(error) MOVED 5798 192.168.226.22:7003
#使用-c参数连接节点后插入数据,结果可以正常插入,他会自动插入到对应的哈希槽
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -c -h 192.168.226.23 -p 7006
192.168.226.23:7006> set age grg
-> Redirected to slot [741] located at 192.168.226.21:7001
OK
192.168.226.21:7001> set name lisi
-> Redirected to slot [5798] located at 192.168.226.22:7003
OK
在 Redis 集群中,每个主节点和从节点负责特定的哈希槽范围。哈希槽(hash slot)是 Redis 集群中的一个概念,用于将键分配到不同的节点。Redis 集群将键映射到 16384 个哈希槽,然后将这些哈希槽分配给不同的节点。使用 -c 参数(即“cluster mode”)来运行 redis-cli 是因为这个模式会处理 Redis 集群的特定行为,特别是当节点之间存在键的重定向时。这是因为 Redis 集群中的每个键都映射到特定的哈希槽,而每个哈希槽又由集群中的特定节点负责。如果你尝试在没有集群模式的情况下访问不属于该节点的键,Redis 将返回一个 MOVED 错误,指示你重定向到正确的节点。当你使用 redis-cli 连接到 Redis 集群并进行操作时,集群模式会自动处理这些重定向。这意味着,如果你试图访问一个不在当前节点处理范围内的键,redis-cli 将自动重定向你的请求到正确的节点。
实验二:
随机连接一个节点,这次使用-c参数连接后插入多条数据
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -c -h 192.168.226.23 -p 7006
192.168.226.23:7006> set age grg
-> Redirected to slot [741] located at 192.168.226.21:7001
OK
192.168.226.21:7001> set name lisi
-> Redirected to slot [5798] located at 192.168.226.22:7003
OK
192.168.226.22:7003>
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -c -h 192.168.226.22 -p 7004
192.168.226.22:7004> keys *
1) "age"
192.168.226.22:7004> set a b
-> Redirected to slot [15495] located at 192.168.226.23:7005
OK
192.168.226.23:7005> set e g
OK
192.168.226.23:7005> set q a
OK
192.168.226.23:7005> set age 99
-> Redirected to slot [741] located at 192.168.226.21:7001
OK
192.168.226.21:7001> keys *
1) "age"
192.168.226.21:7001> set dgd sdf
-> Redirected to slot [14644] located at 192.168.226.23:7005
OK
192.168.226.23:7005> set 1 2
-> Redirected to slot [9842] located at 192.168.226.22:7003
OK
192.168.226.22:7003> keys *
1) "name"
2) "1"
192.168.226.22:7003> get age
-> Redirected to slot [741] located at 192.168.226.21:7001
"99"
192.168.226.21:7001> get e
-> Redirected to slot [15363] located at 192.168.226.23:7005
"g"
通过多次插入数据和查看发现,在插入时会被重定向,数据会被重定向到对应的哈希槽,同时所处的节点也会随之移动,并且查看所有key时,只能看到当前节点机器的key,随便看不到别的节点的key,但是使用get去查看别的节点存在的key,也是可以看到其对应的值的,只是在自己所处的节点不能看到别的节点的key。
简述总结:
当使用 -c
参数连接 Redis 集群时,会观察到以下行为和特点:
-
自动键重定向:
- 当执行命令时,
redis-cli
会根据键的哈希槽信息自动将命令发送到负责该键的节点上执行。 - 如果键的哈希槽不在当前连接的节点上,
redis-cli
会自动重定向命令到正确的节点执行,执行成功后返回结果。
- 当执行命令时,
-
节点的键查看限制:
- 每次连接到一个节点后,只能查看该节点负责的键,而不能查看整个集群的所有键。
- 这意味着在一个节点上执行
keys *
命令只会返回该节点负责的键列表,而不是整个集群的所有键。
-
位置变动:
- 如果集群的主从节点发生变化或者数据迁移,同一个键可能会被分配到不同的节点上。
- 因此,多次连接并查看键的位置可能会发现键在不同节点上的分布情况有所改变。
-
集群管理和数据一致性:
- Redis 集群通过哈希槽来管理数据分片和负载均衡,自动将数据分散到不同的节点上。
- 当节点加入或离开集群时,集群会重新分配哈希槽,保证数据的高可用性和一致性。
实验三:
现在实验挂掉一个节点和挂掉一对主从节点测试。
从前面看到的分配的主从配对信息中,选择从节点192.168.226.21:7002和主节点192.168.226.23:7005来测试
首先将192.168.226.23:7005关闭服务,看从节点变化。
对192.168.226.23主机操作:
[root@localhost local]# /usr/local/redis7005/src/redis-cli -h 192.168.226.23 -p 7005 shutdown
[root@localhost ~]# ss -tnlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 0.0.0.0:17006 0.0.0.0:* users:(("redis-server",pid=1783,fd=9))
LISTEN 0 511 0.0.0.0:7006 0.0.0.0:* users:(("redis-server",pid=1783,fd=6))
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=858,fd=3))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=858,fd=4))
#查看集群中每个节点的状态
[root@localhost ~]# /usr/local/redis7006/src/redis-cli -h 192.168.226.23 -p 7006 cluster nodes
4cad4eebb85a849614ecaffeeb4b73da032fd974 192.168.226.22:7003@17003 master - 0 1719492508192 3 connected 5461-10922
e4264f2bfaff2546625b9a8f559a0e822c5e24e1 192.168.226.21:7001@17001 master - 0 1719492507000 1 connected 0-5460
870ed4837bcfc5d8e455c04ff4e2ec39156a652b 192.168.226.21:7002@17002 master - 0 1719492507187 7 connected 10923-16383
171b2751e63e86aa5335c149804a0e435dbb6f7f 192.168.226.23:7006@17006 myself,slave 4cad4eebb85a849614ecaffeeb4b73da032fd974 0 1719492508000 6 connected
852c2c534e007a5155f96fba95c8333e334a5c3e 192.168.226.22:7004@17004 slave e4264f2bfaff2546625b9a8f559a0e822c5e24e1 0 1719492506179 4 connected
b0dc2767920f8e319e59709a88252cd46cfdda6d 192.168.226.23:7005@17005 master,fail - 1719492406717 1719492406616 5 disconnected
可以发现把一个主节点关闭后,在集群信息中会被标记故障,然后对应的从节点会变成主机点
现在把192.168.226.23:7005的redis服务启动再观察:
#启动192.168.226.23:7005的redis服务
[root@localhost local]# /usr/local/redis7005/src/redis-server /usr/local/redis7005/redis.conf
[root@localhost local]# ss -tnlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 0.0.0.0:17006 0.0.0.0:* users:(("redis-server",pid=1783,fd=9))
LISTEN 0 511 0.0.0.0:17005 0.0.0.0:* users:(("redis-server",pid=1836,fd=9))
LISTEN 0 511 0.0.0.0:7006 0.0.0.0:* users:(("redis-server",pid=1783,fd=6))
LISTEN 0 511 0.0.0.0:7005 0.0.0.0:* users:(("redis-server",pid=1836,fd=6))
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=858,fd=3))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=858,fd=4))
[root@localhost ~]# /usr/local/redis7006/src/redis-cli -h 192.168.226.22 -p 7003 -c
192.168.226.22:7003> cluster nodes
978977953ce8a5ee9a3363863f24b4ce902fc216 192.168.226.21:7001@17001 master - 0 1719499652547 1 connected 0-5460
2544360a6e3ea711151312abb829037fe1b72163 192.168.226.23:7005@17005 slave 3473b893f94e01fee0f7be54cb53007440e487ea 0 1719499653000 7 connected
c1250f1610d7328dba13a030f89257b480c0d781 192.168.226.22:7003@17003 myself,master - 0 1719499653000 3 connected 5461-10922
faa30f7980bda533b25558ad6656dee6f3a40566 192.168.226.22:7004@17004 slave 978977953ce8a5ee9a3363863f24b4ce902fc216 0 1719499653047 4 connected
51db12ce426015bbabda015e2bb3564f0858b43e 192.168.226.23:7006@17006 slave c1250f1610d7328dba13a030f89257b480c0d781 0 1719499653852 6 connected
3473b893f94e01fee0f7be54cb53007440e487ea 192.168.226.21:7002@17002 master - 0 1719499652547 7 connected 10923-16383
192.168.226.22:7003>
可以看到192.168.226.23:7005的redis再开启服务后就变成了从节点,原来一组的从节点192.168.226.21:7002变成了主节点。
现在将这一对主从节点都停止服务测试:
#对192.168.226.23主机操作
[root@localhost ~]# /usr/local/redis7005/src/redis-cli -h 192.168.226.23 -p 7005 shutdown
#对192.168.226.21主机操作
[root@localhost ~]# /usr/local/redis7002/src/redis-cli -h 192.168.226.21 -p 7002 shutdown
#使用192.168.226.21主机连接redis
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.21 -p 7001 -c
192.168.226.21:7001> cluster nodes
faa30f7980bda533b25558ad6656dee6f3a40566 192.168.226.22:7004@17004 slave 978977953ce8a5ee9a3363863f24b4ce902fc216 0 1719403248009 4 connected
978977953ce8a5ee9a3363863f24b4ce902fc216 192.168.226.21:7001@17001 myself,master - 0 1719403227000 1 connected 0-5460
2544360a6e3ea711151312abb829037fe1b72163 192.168.226.23:7005@17005 slave,fail 3473b893f94e01fee0f7be54cb53007440e487ea 1719403235885 1719403234851 7 disconnected
3473b893f94e01fee0f7be54cb53007440e487ea 192.168.226.21:7002@17002 master,fail - 1719403230400 1719403229172 7 disconnected 10923-16383
c1250f1610d7328dba13a030f89257b480c0d781 192.168.226.22:7003@17003 master - 0 1719403247374 3 connected 5461-10922
51db12ce426015bbabda015e2bb3564f0858b43e 192.168.226.23:7006@17006 slave c1250f1610d7328dba13a030f89257b480c0d781 0 1719403247798 6 connected
192.168.226.21:7001> keys *
1) "www"
2) "age"
192.168.226.21:7001> get www
(error) CLUSTERDOWN The cluster is down
192.168.226.21:7001> set big 8888
(error) CLUSTERDOWN The cluster is down
192.168.226.21:7001>
可以看到不能看数据,也不能写数据。CLUSTERDOWN The cluster is down
错误表明 Redis 集群当前处于非活动状态,可能是因为集群中的某些节点无法正常通信或集群配置出现了问题。因此,当一对互为主从的节点宕机,则集群不可用。
现在将原来先将192.168.226.23:7005开启服务
[root@localhost local]# /usr/local/redis7005/src/redis-server /usr/local/redis7005/redis.conf
将验证,即便先起来也不代表会先成为master节点。
现在再将192.168.226.21:7002恢复redis服务
[root@localhost ~]# /usr/local/redis7002/src/redis-server /usr/local/redis7002/redis.conf
实验四:
添加节点
此时我们新增一个虚拟机,拷贝两个redis实例并启动
localhost | rocky_linux9.4 | 192.168.226.24 | redis5.0.10 |
确认关闭防火墙和selinux,进行时间同步。
从192.168.226.21主机中拷贝两个redis实例到192.168.226.24主机中。
#对192.168.226.21操作进行拷贝
[root@localhost ~]# scp -r /usr/local/redis7001 root@192.168.226.24:/usr/local/redis7007
[root@localhost ~]# scp -r /usr/local/redis7001 root@192.168.226.24:/usr/local/redis7008
#对192.168.226.24主机修改配置文件
[root@localhost ~]# vim /usr/local/redis7007/redis.conf
#使用:%s/7001/7007/g 然后保存退出
[root@localhost ~]# vim /usr/local/redis7008/redis.conf
#使用:%s/7001/7008/g 然后保存退出
#启动两个redis实例
[root@localhost ~]# /usr/local/redis7007/src/redis-server /usr/local/redis7007/redis.conf
[root@localhost ~]# /usr/local/redis7007/src/redis-server /usr/local/redis7008/redis.conf
#验证启动
[root@localhost ~]# ss -tnlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 0.0.0.0:7008 0.0.0.0:* users:(("redis-server",pid=1416,fd=6))
LISTEN 0 511 0.0.0.0:7007 0.0.0.0:* users:(("redis-server",pid=1411,fd=6))
LISTEN 0 511 0.0.0.0:17007 0.0.0.0:* users:(("redis-server",pid=1411,fd=9))
LISTEN 0 511 0.0.0.0:17008 0.0.0.0:* users:(("redis-server",pid=1416,fd=9))
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=849,fd=3))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=849,fd=4))
要添加节点,首先启动redis实例,用集群中的主机连接任一实例去添加这个新节点。
选择192.168.226.21去操作添加:
#添加主节点
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.21 -p 7002 cluster meet 192.168.226.24 7007
#查看集群中每个节点的状态
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.24 -p 7002 cluster nodes
2544360a6e3ea711151312abb829037fe1b72163 192.168.226.23:7005@17005 slave 3473b893f94e01fee0f7be54cb53007440e487ea 0 1719502625187 7 connected
faa30f7980bda533b25558ad6656dee6f3a40566 192.168.226.22:7004@17004 slave 978977953ce8a5ee9a3363863f24b4ce902fc216 0 1719502623179 1 connected
3473b893f94e01fee0f7be54cb53007440e487ea 192.168.226.21:7002@17002 master - 0 1719502623000 7 connected 10923-16383
c1250f1610d7328dba13a030f89257b480c0d781 192.168.226.22:7003@17003 master - 0 1719502623681 3 connected 5461-10922
94d037d03b44f77db95acbcf6b8fa9ffa5cb95b4 192.168.226.24:7007@17007 myself,slave 978977953ce8a5ee9a3363863f24b4ce902fc216 0 1719502622000 0 connected
978977953ce8a5ee9a3363863f24b4ce902fc216 192.168.226.21:7001@17001 master - 0 1719502624183 1 connected 0-5460
51db12ce426015bbabda015e2bb3564f0858b43e 192.168.226.23:7006@17006 slave c1250f1610d7328dba13a030f89257b480c0d781 0 1719502624000 3 connected
验证集群状态
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.21 -p 7002 cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:7
cluster_size:3
cluster_current_epoch:7
cluster_my_epoch:7
cluster_stats_messages_ping_sent:3969
cluster_stats_messages_pong_sent:3466
cluster_stats_messages_meet_sent:1
cluster_stats_messages_update_sent:2
cluster_stats_messages_sent:7438
cluster_stats_messages_ping_received:3466
cluster_stats_messages_pong_received:3970
cluster_stats_messages_received:7436
#再添加一个节点
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.21 -p 7001 cluster meet 192.168.226.24 7008
#给新增的节点设置其对应的主节点,后面的字符串就是主节点的ID,通过前面用cluster nodes获取到的
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.24 -p 7008 cluster replicate c1250f1610d7328dba13a030f89257b480c0d781
这两个命令用法:
/path路径/redis/src/redis-cli -h <已有节点IP> -p <已有节点端口> cluster meet <新节点IP> <新节点端口> /path路径/redis/src/redis-cli -h <新节点IP> -p <新节点端口> cluster replicate <已有节点ID>
注:
添加节点有一种情况是添加进去就是master,有一种情况添加后就是slave ,如果是slave那么执行使用cluster reset 重置这个节点再次重新添加至集群内尝试。
/usr/local/redis7001/src/redis-cli -h 192.168.226.24 -p 7007 cluster reset
自动分配槽位
[root@localhost ~]# /usr/local/redis7001/src/redis-cli --cluster rebalance 192.168.226.24:7007
>>> Performing Cluster Check (using node 192.168.226.24:7007)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
*** No rebalancing needed! All nodes are within the 2.00% threshold.
[root@localhost ~]# /usr/local/redis7001/src/redis-cli --cluster rebalance 192.168.226.24:7008
>>> Performing Cluster Check (using node 192.168.226.24:7008)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
*** No rebalancing needed! All nodes are within the 2.00% threshold.
提升节点为master:
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.24 -p 7007 cluster failover
假设我给192.168.226.24:7007 把其从节点提升为主节点,使用CLUSTER FAILOVER命令后,会让原有的注意点之一降级为从节点,其原理解释如下:
在Redis集群中,执行CLUSTER FAILOVER
命令后,所有的从节点都会尝试进行故障转移,结果是你指定的节点变为了主节点。执行过程中的变化可以解释为什么会发生角色改变。
执行的步骤
-
初始状态:
192.168.226.24:7007
为从节点。192.168.226.21:7001
、192.168.226.21:7002
、192.168.226.22:7003
是主节点。
-
执行故障转移:
- 当你在
192.168.226.24:7007
(原从节点)执行CLUSTER FAILOVER
命令时,这个从节点被提升为主节点。
- 当你在
故障转移过程
故障转移过程中:
- 原主节点(
192.168.226.21:7001
)的角色变为了从节点,以保持数据的高可用性和一致性。 - 具体来说,执行
CLUSTER FAILOVER
命令后,192.168.226.24:7007
从节点被提升为主节点,原主节点(192.168.226.21:7001
)被降级为从节点。这就是为什么看到的新输出中192.168.226.24:7007
变为了主节点,而192.168.226.21:7001
变为了从节点。
新的集群状态解释
新的状态如下:
-
主节点:
192.168.226.24:7007
192.168.226.21:7002
192.168.226.22:7003
-
从节点:
192.168.226.21:7001
(从原主节点降级)192.168.226.23:7005
192.168.226.22:7004
192.168.226.24:7008
192.168.226.23:7006
新状态变更后,新的主节点和从节点的对应关系保持如下:
- 新主节点
192.168.226.24:7007
接管了原主节点192.168.226.21:7001
的插槽范围0-5460
。
变化主要是为了保持群集的高可用性和数据的一致性,同时你也成功完成了将从节点提升为主节点的操作。
#验证重新平衡
[root@localhost ~]# /usr/local/redis7001/src/redis-cli --cluster check 192.168.226.24:7008
192.168.226.24:7008 (7a98972a...) -> 1 keys | 5462 slots | 2 slaves.
192.168.226.23:7005 (2544360a...) -> 3 keys | 5461 slots | 1 slaves.
192.168.226.24:7007 (94d037d0...) -> 2 keys | 5461 slots | 2 slaves.
[OK] 6 keys in 3 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 192.168.226.24:7008)
M: 7a98972ab9a038538c2106d1e6c52915d5e3999d 192.168.226.24:7008
slots:[5461-10922] (5462 slots) master
2 additional replica(s)
S: 3473b893f94e01fee0f7be54cb53007440e487ea 192.168.226.21:7002
slots: (0 slots) slave
replicates 2544360a6e3ea711151312abb829037fe1b72163
S: 51db12ce426015bbabda015e2bb3564f0858b43e 192.168.226.23:7006
slots: (0 slots) slave
replicates 7a98972ab9a038538c2106d1e6c52915d5e3999d
M: 2544360a6e3ea711151312abb829037fe1b72163 192.168.226.23:7005
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: faa30f7980bda533b25558ad6656dee6f3a40566 192.168.226.22:7004
slots: (0 slots) slave
replicates 94d037d03b44f77db95acbcf6b8fa9ffa5cb95b4
S: 978977953ce8a5ee9a3363863f24b4ce902fc216 192.168.226.21:7001
slots: (0 slots) slave
replicates 94d037d03b44f77db95acbcf6b8fa9ffa5cb95b4
S: c1250f1610d7328dba13a030f89257b480c0d781 192.168.226.22:7003
slots: (0 slots) slave
replicates 7a98972ab9a038538c2106d1e6c52915d5e3999d
M: 94d037d03b44f77db95acbcf6b8fa9ffa5cb95b4 192.168.226.24:7007
slots:[0-5460] (5461 slots) master
2 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
实验五:
使用gorget忘记一个redis实例。
在这之前的实验添加了两个节点,并将192.168.226.24:7007的实例提升为master节点,并导致整个集群从节点都会尝试进行故障转移,新的主从信息如下查看:
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.21 -p 7001 cluster nodes
94d037d03b44f77db95acbcf6b8fa9ffa5cb95b4 192.168.226.24:7007@17007 master - 0 1719457085420 8 connected 0-5460
978977953ce8a5ee9a3363863f24b4ce902fc216 192.168.226.21:7001@17001 myself,slave 3473b893f94e01fee0f7be54cb53007440e487ea 0 1719457085000 1 connected
7a98972ab9a038538c2106d1e6c52915d5e3999d 192.168.226.24:7008@17008 master - 0 1719457086078 9 connected 5461-10922
3473b893f94e01fee0f7be54cb53007440e487ea 192.168.226.21:7002@17002 master - 0 1719457086196 11 connected 10923-16383
c1250f1610d7328dba13a030f89257b480c0d781 192.168.226.22:7003@17003 slave 7a98972ab9a038538c2106d1e6c52915d5e3999d 0 1719457086000 9 connected
faa30f7980bda533b25558ad6656dee6f3a40566 192.168.226.22:7004@17004 slave 94d037d03b44f77db95acbcf6b8fa9ffa5cb95b4 0 1719457086519 8 connected
2544360a6e3ea711151312abb829037fe1b72163 192.168.226.23:7005@17005 slave 3473b893f94e01fee0f7be54cb53007440e487ea 0 1719457087281 11 connected
51db12ce426015bbabda015e2bb3564f0858b43e 192.168.226.23:7006@17006 slave 7a98972ab9a038538c2106d1e6c52915d5e3999d 0 1719457087756 9 connected
现在进行忘记一个从节点(后面的字符串是指定节点对应的ID,可在上面查看到的信息找到每个节点对应ID):
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.21 -p 7001 cluster forget 2544360a6e3ea711151312abb829037fe1b72163
再查询每个节点的状态
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.21 -p 7001 cluster nodes
94d037d03b44f77db95acbcf6b8fa9ffa5cb95b4 192.168.226.24:7007@17007 master - 0 1719457172640 8 connected 0-5460
978977953ce8a5ee9a3363863f24b4ce902fc216 192.168.226.21:7001@17001 myself,slave 3473b893f94e01fee0f7be54cb53007440e487ea 0 1719457171000 1 connected
7a98972ab9a038538c2106d1e6c52915d5e3999d 192.168.226.24:7008@17008 master - 0 1719457173425 9 connected 5461-10922
3473b893f94e01fee0f7be54cb53007440e487ea 192.168.226.21:7002@17002 master - 0 1719457172745 11 connected 10923-16383
c1250f1610d7328dba13a030f89257b480c0d781 192.168.226.22:7003@17003 slave 7a98972ab9a038538c2106d1e6c52915d5e3999d 0 1719457173085 9 connected
faa30f7980bda533b25558ad6656dee6f3a40566 192.168.226.22:7004@17004 slave 94d037d03b44f77db95acbcf6b8fa9ffa5cb95b4 0 1719457172000 8 connected
51db12ce426015bbabda015e2bb3564f0858b43e 192.168.226.23:7006@17006 slave 7a98972ab9a038538c2106d1e6c52915d5e3999d 0 1719457172306 9 connected
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.22 -p 7004 cluster nodes
94d037d03b44f77db95acbcf6b8fa9ffa5cb95b4 192.168.226.24:7007@17007 slave faa30f7980bda533b25558ad6656dee6f3a40566 0 1719551425478 12 connected
2544360a6e3ea711151312abb829037fe1b72163 192.168.226.23:7005@17005 slave 3473b893f94e01fee0f7be54cb53007440e487ea 0 1719551425000 11 connected
51db12ce426015bbabda015e2bb3564f0858b43e 192.168.226.23:7006@17006 slave 7a98972ab9a038538c2106d1e6c52915d5e3999d 0 1719551425804 9 connected
7a98972ab9a038538c2106d1e6c52915d5e3999d 192.168.226.24:7008@17008 master - 0 1719551426555 9 connected 5461-10922
c1250f1610d7328dba13a030f89257b480c0d781 192.168.226.22:7003@17003 slave 7a98972ab9a038538c2106d1e6c52915d5e3999d 0 1719551425000 9 connected
faa30f7980bda533b25558ad6656dee6f3a40566 192.168.226.22:7004@17004 myself,master - 0 1719551424000 12 connected 0-5460
3473b893f94e01fee0f7be54cb53007440e487ea 192.168.226.21:7002@17002 master - 0 1719551426000 11 connected 10923-16383
978977953ce8a5ee9a3363863f24b4ce902fc216 192.168.226.21:7001@17001 slave 3473b893f94e01fee0f7be54cb53007440e487ea 0 1719551425000 11 connected
使用forget只是在当前节点忘记了指定ID的节点信息,但是其他节点还是存在这个信息。
使用 CLUSTER FORGET
命令来忘记一个 Redis 集群节点时,这个命令实际上是从当前节点的集群配置中移除了指定的节点信息。但是,这并不意味着该节点从整个集群中完全消失了。
集群中的其他节点可能仍然知道这个被忘记的节点,并且 cluster_known_nodes
的计数可能会继续包含它,直到这些节点也执行了 CLUSTER FORGET
命令或者通过集群的自动重新配置过程(如故障转移或重新平衡)来更新它们的集群配置。
如果在 Redis 集群中的所有其他节点上都使用 CLUSTER FORGET
命令忘记了7005节点的集群ID,那么从集群管理的角度来看,7005节点就已经从集群配置中被移除了。然而,仅仅这样做并不意味着7005节点已经停止运行或已从物理上删除。如果还需要确保7005节点不再运行并且释放其占用的资源,可以则停止7005节点的服务,删除7005节点的数据和配置文件等方法。
请注意,如果7005节点在 CLUSTER FORGET
操作之后重新启动,并且它仍然保留有之前的集群状态信息(特别是 nodes.conf
文件),它可能会尝试重新加入集群。因此,彻底删除7005节点的数据和配置文件是确保它不再参与集群的关键步骤。
执行forget后,重启7005节点后,在使用forget那个节点那又可以查看到7005节点的信息了
实验六:
在实验五中仅仅使用forgrt命令测试忘记节点,那么在重新启动被forget的redis节点,就又可以恢复了。
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.21 -p 7001 cluster nodes
94d037d03b44f77db95acbcf6b8fa9ffa5cb95b4 192.168.226.24:7007@17007 slave faa30f7980bda533b25558ad6656dee6f3a40566 0 1719459359290 12 connected
978977953ce8a5ee9a3363863f24b4ce902fc216 192.168.226.21:7001@17001 myself,slave 3473b893f94e01fee0f7be54cb53007440e487ea 0 1719459355000 1 connected
7a98972ab9a038538c2106d1e6c52915d5e3999d 192.168.226.24:7008@17008 master - 0 1719459360597 9 connected 5461-10922
3473b893f94e01fee0f7be54cb53007440e487ea 192.168.226.21:7002@17002 master - 0 1719459360171 11 connected 10923-16383
c1250f1610d7328dba13a030f89257b480c0d781 192.168.226.22:7003@17003 slave 7a98972ab9a038538c2106d1e6c52915d5e3999d 0 1719459359513 9 connected
faa30f7980bda533b25558ad6656dee6f3a40566 192.168.226.22:7004@17004 master - 0 1719459360054 12 connected 0-5460
2544360a6e3ea711151312abb829037fe1b72163 192.168.226.23:7005@17005 slave 3473b893f94e01fee0f7be54cb53007440e487ea 0 1719459360597 11 connected
51db12ce426015bbabda015e2bb3564f0858b43e 192.168.226.23:7006@17006 slave 7a98972ab9a038538c2106d1e6c52915d5e3999d 0 1719459358413 9 connected
接下来尝试节点缩容。
被缩容节点和接收数据槽的几点都要求为主节点才可,在Redis集群中,只有主节点才能拥有哈希槽(slots)。
根据上述集群信息和对应ID,以及下述语法
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.21 -p 7001 --cluster reshard 192.168.226.21:7002 --cluster-from 3473b893f94e01fee0f7be54cb53007440e487ea --cluster-to 7a98972ab9a038538c2106d1e6c52915d5e3999d --cluster-slots 5461 --cluster-yes
# --cluster-from 要缩容的主节点id
# --cluster-to 缩容之后的数据槽点分给哪一个master
# --cluster-slots 要缩容的主节点id的槽位数量
# --cluster-yes 可以自动执行而无需手动确认(可加可不加)
再次查询信息
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.21 -p 7001 cluster nodes
94d037d03b44f77db95acbcf6b8fa9ffa5cb95b4 192.168.226.24:7007@17007 slave faa30f7980bda533b25558ad6656dee6f3a40566 0 1719460937784 12 connected
978977953ce8a5ee9a3363863f24b4ce902fc216 192.168.226.21:7001@17001 myself,slave 7a98972ab9a038538c2106d1e6c52915d5e3999d 0 1719460936000 1 connected
7a98972ab9a038538c2106d1e6c52915d5e3999d 192.168.226.24:7008@17008 master - 0 1719460936000 13 connected 5461-16383
3473b893f94e01fee0f7be54cb53007440e487ea 192.168.226.21:7002@17002 master - 0 1719460937324 11 connected
c1250f1610d7328dba13a030f89257b480c0d781 192.168.226.22:7003@17003 slave 7a98972ab9a038538c2106d1e6c52915d5e3999d 1719460938127 1719460935871 13 connected
faa30f7980bda533b25558ad6656dee6f3a40566 192.168.226.22:7004@17004 master - 0 1719460937903 12 connected 0-5460
2544360a6e3ea711151312abb829037fe1b72163 192.168.226.23:7005@17005 slave 7a98972ab9a038538c2106d1e6c52915d5e3999d 0 1719460937022 13 connected
51db12ce426015bbabda015e2bb3564f0858b43e 192.168.226.23:7006@17006 slave 7a98972ab9a038538c2106d1e6c52915d5e3999d 0 1719460936206 13 connected
实验七:
删除一个从节点
(推荐先删除从节点,后删除主几点)
下面是删除的命令,后面要跟的是被删除节点IP和端口,然后就是ID
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.21 -p 7001 --cluster del-node 192.168.226.23:7006 51db12ce426015bbabda015e2bb3564f0858b43e
可以看到没有7006的节点了。
删除主节点
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.21 -p 7001 --cluster del-node 192.168.226.21:7002 3473b893f94e01fee0f7be54cb53007440e487ea
错误原因:
[root@localhost ~]# /usr/local/redis7001/src/redis-cli -h 192.168.226.21 -p 7001 --cluster del-node 192.168.226.24:7008 7a98972ab9a038538c2106d1e6c52915d5e3999d
>>> Removing node 7a98972ab9a038538c2106d1e6c52915d5e3999d from cluster 192.168.226.24:7008
[ERR] Node 192.168.226.24:7008 is not empty! Reshard data away and try again.
错误信息提示正在尝试从集群中删除一个非空的节点(7a98972ab9a038538c2106d1e6c52915d5e3999d
),但是该节点上仍然有哈希槽(slots)和数据。在Redis集群中,不能直接删除一个包含数据的节点,因为这样会丢失数据,只有当节点是空的(即它不拥有任何哈希槽和数据)时,才能使用redis-cli --cluster del-node
命令来删除该节点。
实验八:
删除集群
Redis集群创建好后,一般会有以下文件生成:
$ tree
.
├── appendonly.aof
├── dump.rdb
├── nodes-7000.conf
├── redis.conf
└── redis-server
0 directories, 5 files
其中,nodes-*.conf记录了Redis集群的信息。
要想删除一个集群,首先关闭Redis服务,方法如下:
redis-cli -h 127.0.0.1 -p 7000 shutdown
关闭所有集群上节点后,进入各个节点文件夹,删除以下文件:
appendonly.aof
dump.rdb
nodes-7000.conf
批量删除指令如下:
rm -f ./*/nodes-*.conf ./*/appendonly.aof ./*/dump.rdb
ok,至此,旧集群已经不复存在,只留下了redis服务进程和配置文件。