Redis 三种模式
主从模式
Redis 虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况。为了分担读压力,Redis 支持主从复制,Redis 的主从结构可以采用一主多从或者级联结构。
Redis 怎么实现主从复制
- 从服务器初始化时进行全量同步
- 初始化完成后执行增量同步
优点: 实现数据备份,做到读写分离
缺点: 当主节点发生故障掉线时,需要人工进行:故障转移
哨兵模式
可以说是主从复制的升级版本,增加了一个新的角色。由一个或多个哨兵实例组成的哨兵系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器。
优点: 如果 Master 异常,则会进行 Master -> slave 转换,自动实现故障转移。将其中一个 Slave 作为 Master,之前的 Master 重新上线后作为 Slave;
缺点: 如果是从节点下线了,哨兵是不会对其进行故障转移的,连接从节点的客户端也无法获取到新的可用从节点
集群模式
任何两个节点之间都是相互连通的。客户端可以与任何一个节点相连接,然后就可以访问集群中的任何一个节点。对其进行存取和其他操作。一般集群建议搭建三主三从架构,三主提供服务,三从提供备份功能。每一个节点都存有这个集群所有主节点以及从节点的信息。
掉线判断: 过程是集群中所有 master 参与,如果半数以上 master 节点与某个 master 节点通信超时(cluster-node-timeout),认为该 master 节点挂掉.
什么时候整个集群不可用(cluster_state:fail)?
(1)如果集群任意 master 挂掉,且当前 master 没有 slave,集群进入 fail 状态;
(2)如果集群超过半数以上 master 挂掉,无论是否有 slave,集群进入 fail 状态;
三主三从架构
主机名 | IP地址 | 系统版本 | 端口号 | 节点 |
---|---|---|---|---|
redis01 | 192.168.0.41 | Ubuntu Server 24.04 | 6381 | master |
redis01 | 192.168.0.41 | Ubuntu Server 24.04 | 6382 | slave -> redis02 |
redis02 | 192.168.0.42 | Ubuntu Server 24.04 | 6381 | master |
redis02 | 192.168.0.42 | Ubuntu Server 24.04 | 6382 | slave -> redis03 |
redis03 | 192.168.0.43 | Ubuntu Server 24.04 | 6381 | master |
redis03 | 192.168.0.43 | Ubuntu Server 24.04 | 6382 | slave -> redis01 |
部署 Redis 实例
在每台机器上下载 Redis 源码包
1
wget https://download.redis.io/releases/redis-6.2.14.tar.gz
安装 Redis 依赖
1
apt install -y gcc make
解压,编译安装 Redis
1
2
3
4
5tar xf redis-6.2.14.tar.gz -C /usr/local/
cd /usr/local/redis-6.2.14
make && make install在每个节点执行以下命令,创建两个实例的配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30# 创建节点配置文件路径
mkdir -p /data/redis_cluster/redis_{6381,6382}/{conf,data,logs,pid}
# 创建 6381 端口实例的配置文件
cat > /data/redis_cluster/redis_6381/conf/redis_6381.conf <<EOF
bind 0.0.0.0
port 6381
daemonize yes
logfile /data/redis_cluster/redis_6381/logs/redis_6381.log
pidfile /data/redis_cluster/redis_6381/pid/redis_6381.log
dbfilename "redis_6381.rdb"
dir /data/redis_cluster/redis_6381/data
cluster-enabled yes
cluster-config-file node_6381.conf
cluster-node-timeout 15000
EOF
# 创建 6382 端口实例的配置文件
cat > /data/redis_cluster/redis_6382/conf/redis_6382.conf <<EOF
bind 0.0.0.0
port 6382
daemonize yes
logfile /data/redis_cluster/redis_6382/logs/redis_6382.log
pidfile /data/redis_cluster/redis_6382/pid/redis_6382.log
dbfilename "redis_6382.rdb"
dir /data/redis_cluster/redis_6382/data
cluster-enabled yes
cluster-config-file node_6382.conf
cluster-node-timeout 15000
EOF每个节点执行以下命令启动所有实例
1
2
3# 启动 6381 端口实例
redis-server /data/redis_cluster/redis_6381/conf/redis_6381.conf
redis-server /data/redis_cluster/redis_6382/conf/redis_6382.conf查看端口和进程,每个节点启动了 cluster 后,进程名上会增加 cluster。每个 redis 节点会开放两个端口,服务端口 6381,集群通信端口 16381(在服务端口基础上增加 10000)
1
2
3
4
5
6
7
8
9
10
11# 查看进程
ps aux | grep redis
root 6923 0.1 0.1 51956 5056 ? Ssl 14:05 0:00 redis-server 0.0.0.0:6382 [cluster]
root 6938 0.0 0.1 51956 4928 ? Ssl 14:06 0:00 redis-server 0.0.0.0:6381 [cluster]
# 查看端口
netstat -lnpt | grep redis
tcp 0 0 0.0.0.0:16382 0.0.0.0:* LISTEN 6923/redis-server 0
tcp 0 0 0.0.0.0:16381 0.0.0.0:* LISTEN 6938/redis-server 0
tcp 0 0 0.0.0.0:6382 0.0.0.0:* LISTEN 6923/redis-server 0
tcp 0 0 0.0.0.0:6381 0.0.0.0:* LISTEN 6938/redis-server 0查看集群信息文件内容,集群模式的 redis 除了原有的配置文件之外又增加了一个集群配置文件,当集群内节点信息发生变化时,如添加节点,节点下线,故障转移等,节点都会自动保存集群状态到配置文件,redis 自动维护集群配置文件,不需要手动修改防止节点重启时产生错乱。
1
2
3
4
5
6
7# cat /data/redis_cluster/redis_6381/data/node_6381.conf
6522cb4d6f75675ba8382d171a61879318da0c70 :0@0 myself,master - 0 0 0 connected
vars currentEpoch 0 lastVoteEpoch 0
# cat /data/redis_cluster/redis_6382/data/node_6382.conf
0574bcadc56f0dc828b9e23dffbe1fc7a7d587d9 :0@0 myself,master - 0 0 0 connected
vars currentEpoch 0 lastVoteEpoch 0也可以登录 redis 进行查看
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# redis-cli -h 192.168.0.41 -p 6381 cluster nodes
e5305b758878236e01c6af2982b2ca6452efd820 :6381@16381 myself,master - 0 0 0 connected
# redis-cli -h 192.168.0.41 -p 6382 cluster nodes
0e628615c2d54728fbca2405f48f4d45a025ba0c :6382@16382 myself,master - 0 0 0 connected
# redis-cli -h 192.168.0.42 -p 6381 cluster nodes
6522cb4d6f75675ba8382d171a61879318da0c70 :6381@16381 myself,master - 0 0 0 connected
# redis-cli -h 192.168.0.42 -p 6382 cluster nodes
0574bcadc56f0dc828b9e23dffbe1fc7a7d587d9 :6382@16382 myself,master - 0 0 0 connected
# redis-cli -h 192.168.0.43 -p 6381 cluster nodes
2352b7c6eea41aa54857b58af292d4a34e00b502 :6381@16381 myself,master - 0 0 0 connected
# redis-cli -h 192.168.0.43 -p 6382 cluster nodes
288d1a2831b0b4e2337ef33d7ff9779b9d64bcb5 :6382@16382 myself,master - 0 0 0 connected
配置 Cluster 集群互相发现
cluster 集群互相发现只需要在一个节点上配置,所有节点都会接收到配置信息并自动加入到配置文件中。
1
2
3
4
5
6
7
8
9
10
11
12# 在 redis01 的 6381 节点上配置所有节点的互相发现
# redis-cli -h 192.168.0.41 -p 6381
192.168.0.41:6381> CLUSTER MEET 192.168.0.41 6382
OK
192.168.0.41:6381> CLUSTER MEET 192.168.0.42 6381
OK
192.168.0.41:6381> CLUSTER MEET 192.168.0.42 6382
OK
192.168.0.41:6381> CLUSTER MEET 192.168.0.43 6381
OK
192.168.0.41:6381> CLUSTER MEET 192.168.0.43 6382
OK在每个节点查看集群配置文件
1
2
3
4
5
6
7
8# cat /data/redis_cluster/redis_6381/data/node_6381.conf
a6af0ac3bb5d4edd8ff3d5bcbe4f194c54a4a487 192.168.0.42:6381@16381 master - 0 1721462433000 2 connected
7d23f115110e1c7261a698c4a55932160450987d 192.168.0.42:6382@16382 master - 0 1721462433000 3 connected
2a25c389e4c5bf7df461ada1482e11c10c7b52ff 192.168.0.43:6382@16382 master - 0 1721462432341 5 connected
fc55f90ff13682ac66c16e148eb8fcb39c381750 192.168.0.41:6381@16381 myself,master - 0 1721462432000 0 connected
855c88401ba6d908b30e8220ec556f1cf4da9133 192.168.0.41:6382@16382 master - 0 1721462433863 1 connected
883846258a3aa46cb4c04da170df8124eb0172bb 192.168.0.43:6381@16381 master - 0 1721462432847 4 connected
vars currentEpoch 5 lastVoteEpoch 0也可以通过
CLUSTER NODES
指令查看节点信息1
2
3
4
5
6
7192.168.0.41:6381> CLUSTER NODES
a6af0ac3bb5d4edd8ff3d5bcbe4f194c54a4a487 192.168.0.42:6381@16381 master - 0 1721462609000 2 connected
7d23f115110e1c7261a698c4a55932160450987d 192.168.0.42:6382@16382 master - 0 1721462611589 3 connected
2a25c389e4c5bf7df461ada1482e11c10c7b52ff 192.168.0.43:6382@16382 master - 0 1721462608000 5 connected
fc55f90ff13682ac66c16e148eb8fcb39c381750 192.168.0.41:6381@16381 myself,master - 0 1721462608000 0 connected
855c88401ba6d908b30e8220ec556f1cf4da9133 192.168.0.41:6382@16382 master - 0 1721462610580 1 connected
883846258a3aa46cb4c04da170df8124eb0172bb 192.168.0.43:6381@16381 master - 0 1721462609572 4 connected
配置 Cluster 集群分配
redis Cluster 通讯流程
集群内消息传递是同步的,在分布式存储中需要提供维护节点元数据信息的机制,所谓元数据是指:节点负责哪些数据,是否出现故障灯状态信息,redis 集群采用 gossip 协议,gossip 协议工作原理就是节点彼此不断交换信息,一段时间后所有的节点偶会指定集群完整信息,这种方式类似于流言传播,因此只需要在一台节点配置集群信息所有节点都能收到信息。
通信过程:
- 集群中的每一个节点都会单独开辟一个tcp通道用于节点之间彼此通信,通信端口在基础端口上增加 10000
- 每个节点在固定周期内通过特定规则选择结构节点发送 ping 消息
- 接收到 ping 消息的节点用 pong 作为消息响应,集群中每个节点通过一定规则挑选要通信的节点,每个节点可能知道全部节点的信息,也可能知道部分节点信息,只要这些节点彼此可以正常通信,最终他们就会达成一致的状态,当节点出现故障,新节点加入,主从角色变化等,彼此之间不断发生 ping/pong 消息,最终达成同步的模板。
通讯消息类型:gossip,信息交换,常见的消息分为 ping、pong、meet、fail
没有分配槽位时集群的状态,所有节点执行 cluster info
,cluster_state
都是 fail
,fail
状态表示集群不可用,没有分配槽位,cluster_slots
都会显示 0
手动配置集群槽位
每个 cluster 集群都有 16384 个槽位,我们有三台机器,想要手动分配平均就需要使用 16384 除 3
- redis01 0-5461
- redis02 5642-10922
- redis03 10923-16383
分配槽位语法格式(交互式):CLUSTER ADDSLOTS 0 5461
分配槽位语法:redis-cli -h 192.168.81.210 -p 6380 cluster addslots {0…5461}
删除槽位分配语法格式: redis-cli -h 192.168.81.210 -p 6380 cluster delslots {5463…10921}
手动配置槽位
1
2
3
4
5
6root@redis01:~# redis-cli -h 192.168.0.41 -p 6381 cluster addslots {0..5461}
OK
root@redis01:~# redis-cli -h 192.168.0.42 -p 6381 cluster addslots {5462..10922}
OK
root@redis01:~# redis-cli -h 192.168.0.43 -p 6381 cluster addslots {10923..16383}
OK查看集群状态,到目前位置集群已经是可用的了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17root@redis01:~# redis-cli -h 192.168.0.43 -p 6381 cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:5
cluster_my_epoch:4
cluster_stats_messages_ping_sent:820
cluster_stats_messages_pong_sent:785
cluster_stats_messages_sent:1605
cluster_stats_messages_ping_received:784
cluster_stats_messages_pong_received:820
cluster_stats_messages_meet_received:1
cluster_stats_messages_received:1605查看节点信息
1
2
3
4
5
6
7root@redis01:~# redis-cli -h 192.168.0.42 -p 6382 cluster nodes
a6af0ac3bb5d4edd8ff3d5bcbe4f194c54a4a487 192.168.0.42:6381@16381 master - 0 1721463323000 2 connected 5462-10922
855c88401ba6d908b30e8220ec556f1cf4da9133 192.168.0.41:6382@16382 master - 0 1721463325231 1 connected
7d23f115110e1c7261a698c4a55932160450987d 192.168.0.42:6382@16382 myself,master - 0 1721463324000 3 connected
883846258a3aa46cb4c04da170df8124eb0172bb 192.168.0.43:6381@16381 master - 0 1721463323208 4 connected 10923-16383
fc55f90ff13682ac66c16e148eb8fcb39c381750 192.168.0.41:6381@16381 master - 0 1721463324219 0 connected 0-5461
2a25c389e4c5bf7df461ada1482e11c10c7b52ff 192.168.0.43:6382@16382 master - 0 1721463324000 5 connected
创建 key 验证集群是否可用
不是所有的 key 都能插入,有的 key 插入的时候就提示说你应该去 192.168.0.43 上插入,这时手动到对应的主机上执行就可以插入,这是由于 cluster 集群槽位都是分布在不同节点的,每次新建一个 key,都会通过 hash 算法均匀的在不同节点去创建不同节点创建的 key 只由自己节点可以看到自己创建的数据
1
2
3
4
5
6
7
8
9root@redis01:~# redis-cli -h 192.168.0.41 -p 6381
192.168.0.41:6381> set k1 v1
(error) MOVED 12706 192.168.0.43:6381
192.168.0.41:6381> set k2 v2
OK
192.168.0.41:6381> set k3 v3
OK
192.168.0.41:6381> set k4 v4
(error) MOVED 8455 192.168.0.42:6381可以通过 ASK 路由解决创建 key 时提示去别的主机进行创建的问题:
- ASK 路由创建 key 时,如果可以在本机直接创建就会执行创建 key 的命令,如果不能再本机执行,他会根据提示的主机去对应主机上创建 key。
- ASK路径的特性:每次通过 hash 在指定主机上创建了 key 后就会停留在这个主机上
- 只需要执行
redis-cli
时加上-c
参数即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15root@redis01:~# redis-cli -h 192.168.0.41 -p 6381 -c
192.168.0.41:6381> set k4 v4
-> Redirected to slot [8455] located at 192.168.0.42:6381
OK
192.168.0.42:6381> set k5 v5
-> Redirected to slot [12582] located at 192.168.0.43:6381
OK
192.168.0.43:6381> set k6 v6
-> Redirected to slot [325] located at 192.168.0.41:6381
OK
192.168.0.41:6381> set k7 v7
OK
192.168.0.41:6381> set k8 v8
-> Redirected to slot [8331] located at 192.168.0.42:6381
OK
验证 hash 是否均匀
cluster 架构是分布式的,创建的 key 会通过 hash 将数据均已的分布在每台主机的槽位上
插入一千条数据,查看三个节点是否分配均匀,插入的时候使用
-c
,自动在某个节点上插入数据1
for i in {1..1000};do redis-cli -c -h 192.168.0.41 -p 6381 set key_${i} value_${i};done
查看每个节点的数据量,可以看到非常均匀,误差只有一点点
1
2
3
4
5
6root@redis01:~# redis-cli -h 192.168.0.41 -p 6381 dbsize
(integer) 338
root@redis01:~# redis-cli -h 192.168.0.42 -p 6381 dbsize
(integer) 338
root@redis01:~# redis-cli -h 192.168.0.43 -p 6381 dbsize
(integer) 331
配置 Cluster 集群三主三从高可用
三主三从是 Redis Cluster 最常用的架构,每个从节点复制的都不是本机主库的数据,而是其他节点主库的数据,这样即使某一台主机坏掉了,从节点备份还是在其他机器上,这样就做到了高可用,三主三从架构允许最多坏一台主机。
三主三从我们采用交叉复制架构类型,这样可以做到最多坏一台主机集群还是正常可以用的,如果每台主机的 6382 节点都是 6381 节点的备份,那么这台机器坏了,集群就不可用了,因此想要做到高可用,就采用交叉复制
交叉复制的架构,当主节点挂掉了,主节点备份的从节点就会自动成为主节点。
实现步骤:
- 使用
cluster replicate
将主机的 6382 节点交叉成为别的主机 6381 节点的从库 - 查看集群状态即可
配置 rdb 持久化
在所有节点端口的配置文件中加上rdb持久化配置即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15bind 0.0.0.0
port 6381
daemonize yes
logfile /data/redis_cluster/redis_6381/logs/redis_6381.log
pidfile /data/redis_cluster/redis_6381/pid/redis_6381.log
dbfilename "redis_6381.rdb"
dir /data/redis_cluster/redis_6381/data
cluster-enabled yes
cluster-config-file node_6381.conf
cluster-node-timeout 15000
# 持久化配置
save 60 10000
save 300 10
save 900 1重启 Redis
1
2
3
4
5
6
7
8
9
10root@redis01:~# redis-cli -h 192.168.0.41 -p 6381 shutdown
root@redis01:~# redis-cli -h 192.168.0.41 -p 6382 shutdown
root@redis01:~# redis-cli -h 192.168.0.42 -p 6382 shutdown
root@redis01:~# redis-cli -h 192.168.0.42 -p 6381 shutdown
root@redis01:~# redis-cli -h 192.168.0.43 -p 6381 shutdown
root@redis01:~# redis-cli -h 192.168.0.43 -p 6382 shutdown
# 登录每个节点,启动 Redis 服务
redis-server /data/redis_cluster/redis_6381/conf/redis_6381.conf
redis-server /data/redis_cluster/redis_6382/conf/redis_6382.conf
配置三主三从
配置三主三从规范操作步骤:
- 将集群信息粘到 txt 中,只保留下 6381 端口信息
- 配置命令在 txt 中准备好在复制到命令行
主节点我们已经有了,目前 6 个节点全是主节点,我们需要把所有主机的 6382 的主节点配置成从节点,从节点对应的主节点关系:
redis01 的 6382 从节点对应的主节点是 redis02 的 6381 主节点
redis02 的 6382 从节点对应的主节点是 redis03 的 6381 主节点
redis03 的 6382 从节点对应的主节点是 redis01 的 6381 主节点
CLUSTER REPLICATE
是配置当前节点成为某个主节点的从节点,replicate 命令其实就相当于执行了 slaveof,同步了某一个主库,并且在日志中查看到的就是主从同步的过程
查看集群节点信息
1
2
3
4
5
6
7root@redis02:~# redis-cli -h 192.168.0.41 -p 6382 CLUSTER NODES
2a25c389e4c5bf7df461ada1482e11c10c7b52ff 192.168.0.43:6382@16382 master - 0 1721464989000 5 connected
883846258a3aa46cb4c04da170df8124eb0172bb 192.168.0.43:6381@16381 master - 0 1721464991002 4 connected 10923-16383
a6af0ac3bb5d4edd8ff3d5bcbe4f194c54a4a487 192.168.0.42:6381@16381 master - 0 1721464990000 2 connected 5462-10922
fc55f90ff13682ac66c16e148eb8fcb39c381750 192.168.0.41:6381@16381 master - 0 1721464989988 0 connected 0-5461
855c88401ba6d908b30e8220ec556f1cf4da9133 192.168.0.41:6382@16382 myself,master - 0 1721464987000 1 connected
7d23f115110e1c7261a698c4a55932160450987d 192.168.0.42:6382@16382 master - 0 1721464988978 3 connected配置从节点连接主节点,交叉式复制
1
2
3
4
5
6root@redis01:~# redis-cli -h 192.168.0.41 -p 6382 CLUSTER REPLICATE a6af0ac3bb5d4edd8ff3d5bcbe4f194c54a4a487
OK
root@redis01:~# redis-cli -h 192.168.0.42 -p 6382 CLUSTER REPLICATE 883846258a3aa46cb4c04da170df8124eb0172bb
OK
root@redis01:~# redis-cli -h 192.168.0.43 -p 6382 CLUSTER REPLICATE fc55f90ff13682ac66c16e148eb8fcb39c381750
OK再次查看集群节点信息,发现已经是三主三从了
1
2
3
4
5
6
7root@redis01:~# redis-cli -h 192.168.0.43 -p 6382 CLUSTER NODES
2a25c389e4c5bf7df461ada1482e11c10c7b52ff 192.168.0.43:6382@16382 myself,slave fc55f90ff13682ac66c16e148eb8fcb39c381750 0 1721465188000 0 connected
883846258a3aa46cb4c04da170df8124eb0172bb 192.168.0.43:6381@16381 master - 0 1721465186000 4 connected 10923-16383
7d23f115110e1c7261a698c4a55932160450987d 192.168.0.42:6382@16382 slave 883846258a3aa46cb4c04da170df8124eb0172bb 0 1721465189515 4 connected
fc55f90ff13682ac66c16e148eb8fcb39c381750 192.168.0.41:6381@16381 master - 0 1721465189000 0 connected 0-5461
a6af0ac3bb5d4edd8ff3d5bcbe4f194c54a4a487 192.168.0.42:6381@16381 master - 0 1721465190533 2 connected 5462-10922
855c88401ba6d908b30e8220ec556f1cf4da9133 192.168.0.41:6382@16382 slave a6af0ac3bb5d4edd8ff3d5bcbe4f194c54a4a487 0 1721465188499 2 connected配置完主从,可以看到集群中已经有 slave 节点了,并且也是交叉复制的;打开主库的日志可以看到哪个从库同步了主库的日志,打开从库的日志可以看到同步了哪个主库的日志
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20# 查看 redis01 节点的主库日志
root@redis01:~# tail -f /data/redis_cluster/redis_6381/logs/redis_6381.log
...
3080:C 20 Jul 2024 16:45:35.882 * RDB: 0 MB of memory used by copy-on-write
3007:M 20 Jul 2024 16:45:35.958 * Background saving terminated with success
3007:M 20 Jul 2024 16:45:35.958 * Synchronization with replica 192.168.0.43:6382 succeeded
# 查看 redis01 节点的从库日志
root@redis01:~# tail -f /data/redis_cluster/redis_6382/logs/redis_6382.log
...
3022:S 20 Jul 2024 16:44:54.078 * Full resync from master: 837df2c75373c287746f8e5a8f3e3003963f9995:0
3022:S 20 Jul 2024 16:44:54.078 * Discarding previously cached master state.
3022:S 20 Jul 2024 16:44:54.129 * MASTER <-> REPLICA sync: receiving 6514 bytes from master to disk
3022:S 20 Jul 2024 16:44:54.129 * MASTER <-> REPLICA sync: Flushing old data
3022:S 20 Jul 2024 16:44:54.129 * MASTER <-> REPLICA sync: Loading DB in memory
3022:S 20 Jul 2024 16:44:54.137 * Loading RDB produced by version 6.2.14
3022:S 20 Jul 2024 16:44:54.137 * RDB age 0 seconds
3022:S 20 Jul 2024 16:44:54.137 * RDB memory usage when created 2.58 Mb
3022:S 20 Jul 2024 16:44:54.137 # Done loading RDB, keys loaded: 338, keys expired: 0.
3022:S 20 Jul 2024 16:44:54.137 * MASTER <-> REPLICA sync: Finished with success
模拟故障转移
三主三从架构允许最多坏一台主机,模拟将 redis01 机器的主库 6381 挂掉,查看集群间的故障迁移
思路:
- 将 redis01 的 6381 主库关掉,查看集群状态信息是否将 slave 自动切换为 master
- 当 master 上线后会变成一个节点的从库
- 将 master 通过
cluster failover
重新成为主库
模拟坏掉 redis01 的主库并验证就能是否可用
关闭 redis01 的主库
1
root@redis01:~# redis-cli -h 192.168.0.41 -p 6381 shutdown
查看日志,先是由于主库挂了状态变成 fail,当从库变成主库后,状态再次变为 ok
1
2
3
4
5root@redis01:~# tail -f /data/redis_cluster/redis_6382/logs/redis_6382.log
...
3022:S 20 Jul 2024 16:53:43.946 * FAIL message received from 7d23f115110e1c7261a698c4a55932160450987d about fc55f90ff13682ac66c16e148eb8fcb39c381750
3022:S 20 Jul 2024 16:53:43.946 # Cluster state changed: fail
3022:S 20 Jul 2024 16:53:44.768 # Cluster state changed: ok查看集群节点信息
1
2
3
4
5
6
7root@redis01:~# redis-cli -h 192.168.0.41 -p 6382 cluster nodes
2a25c389e4c5bf7df461ada1482e11c10c7b52ff 192.168.0.43:6382@16382 master - 0 1721465669299 6 connected 0-5461
883846258a3aa46cb4c04da170df8124eb0172bb 192.168.0.43:6381@16381 master - 0 1721465670315 4 connected 10923-16383
a6af0ac3bb5d4edd8ff3d5bcbe4f194c54a4a487 192.168.0.42:6381@16381 master - 0 1721465669000 2 connected 5462-10922
fc55f90ff13682ac66c16e148eb8fcb39c381750 192.168.0.41:6381@16381 master,fail - 1721465608352 1721465603000 0 disconnected
855c88401ba6d908b30e8220ec556f1cf4da9133 192.168.0.41:6382@16382 myself,slave a6af0ac3bb5d4edd8ff3d5bcbe4f194c54a4a487 0 1721465668000 2 connected
7d23f115110e1c7261a698c4a55932160450987d 192.168.0.42:6382@16382 slave 883846258a3aa46cb4c04da170df8124eb0172bb 0 1721465671329 4 connected当主库挂掉后,查看集群节点信息时会看到提示主库已经是 fail 状态,此时可用看到 192.168.0.43 机器的 6382 端口成为了 master,192.168.0.41 的 6382 端口是 redis02 的从库,从库变为主库后,集群状态再次变为 ok
查看集群状态
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18root@redis01:~# redis-cli -h 192.168.0.41 -p 6382 cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:2
cluster_stats_messages_ping_sent:1027
cluster_stats_messages_pong_sent:1072
cluster_stats_messages_sent:2099
cluster_stats_messages_ping_received:1072
cluster_stats_messages_pong_received:1023
cluster_stats_messages_fail_received:1
cluster_stats_messages_auth-req_received:1
cluster_stats_messages_received:2097验证集群是否可用
1
2
3
4root@redis01:~# redis-cli -c -h 192.168.0.41 -p 6382 set k1111 v1111
OK
root@redis01:~# redis-cli -c -h 192.168.0.41 -p 6382 set k1112 v1112
OK
redis01 节点的主库恢复
启动 redis01 的 6381 主库
1
root@redis01:~# redis-server /data/redis_cluster/redis_6381/conf/redis_6381.conf
查看集群节点信息
1
2
3
4
5
6
7root@redis01:~# redis-cli -h 192.168.0.41 -p 6381 cluster nodes
855c88401ba6d908b30e8220ec556f1cf4da9133 192.168.0.41:6382@16382 slave a6af0ac3bb5d4edd8ff3d5bcbe4f194c54a4a487 0 1721466162395 2 connected
883846258a3aa46cb4c04da170df8124eb0172bb 192.168.0.43:6381@16381 master - 0 1721466161000 4 connected 10923-16383
2a25c389e4c5bf7df461ada1482e11c10c7b52ff 192.168.0.43:6382@16382 master - 0 1721466161380 6 connected 0-5461
a6af0ac3bb5d4edd8ff3d5bcbe4f194c54a4a487 192.168.0.42:6381@16381 master - 0 1721466160372 2 connected 5462-10922
fc55f90ff13682ac66c16e148eb8fcb39c381750 192.168.0.41:6381@16381 myself,slave 2a25c389e4c5bf7df461ada1482e11c10c7b52ff 0 1721466158000 6 connected
7d23f115110e1c7261a698c4a55932160450987d 192.168.0.42:6382@16382 slave 883846258a3aa46cb4c04da170df8124eb0172bb 0 1721466160000 4 connected
目前主库已经重新上线了,且现在的角色是从库,而原来 192.168.0.43 的从库变成了现在 192.168.0.41 的主库,而且 192.168.0.41 上的两个实例都是从库,192.168.0.43 上的两个实例都是主库;我们需要把关系切换回来,不能让一台机器上同时存在两台主库,以及一台机器上全是从库,每次故障处理后一定要把架构修改会原来的样子。
将恢复的主库重新变为主库
从库切换成主库也特别简单,只需要执行一个 cluster falover
即可变为主库,cluster falover
确实也类似于关系互换,简单理解就是原来的从变成了主,现在的主变成了从,这样一来就可以把故障恢复的主机重新变为主库cluster falover
原理:falover 原理也就是先执行了 slave no one
,然后在对应的由主库变为从库的机器上执行了 slave of
将故障上线的主库重新成为主库
1
2
3root@redis01:~# redis-cli -h 192.168.0.41 -p 6381
192.168.0.41:6381> CLUSTER FAILOVER
OK查看集群信息,192.168.0.41 的发现 6381 重新成为了 master,而 192.168.0.43 的从库变成了slave
1
2
3
4
5
6
7192.168.0.41:6381> CLUSTER NODES
855c88401ba6d908b30e8220ec556f1cf4da9133 192.168.0.41:6382@16382 slave a6af0ac3bb5d4edd8ff3d5bcbe4f194c54a4a487 0 1721466829554 2 connected
883846258a3aa46cb4c04da170df8124eb0172bb 192.168.0.43:6381@16381 master - 0 1721466829000 4 connected 10923-16383
2a25c389e4c5bf7df461ada1482e11c10c7b52ff 192.168.0.43:6382@16382 slave fc55f90ff13682ac66c16e148eb8fcb39c381750 0 1721466826000 7 connected
a6af0ac3bb5d4edd8ff3d5bcbe4f194c54a4a487 192.168.0.42:6381@16381 master - 0 1721466827000 2 connected 5462-10922
fc55f90ff13682ac66c16e148eb8fcb39c381750 192.168.0.41:6381@16381 myself,master - 0 1721466825000 7 connected 0-5461
7d23f115110e1c7261a698c4a55932160450987d 192.168.0.42:6382@16382 slave 883846258a3aa46cb4c04da170df8124eb0172bb 0 1721466827527 4 connected到此 Cluster 集群故障转移成功,集群状态一切正常
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19192.168.0.41:6381> CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:7
cluster_my_epoch:7
cluster_stats_messages_ping_sent:844
cluster_stats_messages_pong_sent:831
cluster_stats_messages_auth-req_sent:5
cluster_stats_messages_mfstart_sent:1
cluster_stats_messages_sent:1681
cluster_stats_messages_ping_received:826
cluster_stats_messages_pong_received:844
cluster_stats_messages_auth-ack_received:3
cluster_stats_messages_received:1673
Redis Cluster需要注意的几点
生产环境数据量可能非常大,当主库故障重新上线时,执行 CLUSTER FAILOVER
会很慢,因为这个就相当于是主从复制切换了,从库(刚上线的原来主库)关闭主从复制,主库(主库坏掉前的从库)同步从库(刚上线的原来主库)数据,然后从库(刚上线的原来主库)重新变为主库,这个时间一定要等,切记,千万不要因为慢在主库上(主库坏掉前的从库)同步手动进行了 CLUSTER REPLICATE
,这样确实会非常快的将主库(主库坏掉前的从库)重新变为从库,但也意味着这个节点数据全部丢失,因为 clusert replicate
相当于 slaveof
,slaveof
会把自己的库清掉,这时候从库(刚上线的原来主库)在执行这 CLUSTER FAILOVER
同步着主库(主库坏掉前的从库)的数据,主库那边执行了 replicate
去同步从库(刚上线的原来主库),从而导致从库(刚上线的原来主库)还没有同步完主库(主库坏掉前的从库的数据),主库(主库坏掉前的从库)数据就丢失,整个集群还是可以用的,只是这个主库节点和从节点数据全部丢失,其他两个主库从库还能使用。
切记,当从库执行 CLUSTER FAILOVER
变为主库时,一定不要在主库上执行 CLUSTER REPLICATE
变为从库,虽然 CLUSTER REPLICATE
变为从库很快,但是会清空自己的数据去同步主库,这时主库还没有数据,因此就会导致数据全部丢失
CLUSTER FAILOVER
:首先执行slave on one
变为一个单独的节点,然后在要变成从库的节点上执行slaveof
,只要从库执行完slave of
,执行CLUSTER FAILOVER
的节点就变成了主库CLUSTER REPLICATE
:只是执行了slaveof
使自身成为从节点
当 redis cluster 主从正在同步时,不要执行 cluster replicate
,当主从复制完在执行,如何看主从是否复制完就要看节点的 rdb 文件是否是 .tmp
结尾的,如果是 .tmp
结尾就说明他们正在同步数据,此时不要对集群做切换操作
小总结:
- 3.0 版本以后推出集群功能
- cluster集群有16384个槽位,误差在2%之间
- 槽位与序号顺序无关,重点是槽的数量
- 通过发现集群,与集群之间实现消息传递
- 配置文件无需手动修改,都是自动生成的
- 分配操作,必须将所有的槽位分配完毕
- 理清复制关系,画图,按照图形执行复制命令
- 当集群状态为ok时,集群才可以正常使用
- 反复测试,批量插入key,验证分配是否均匀
- 测试高可用,关闭任意主节点,集群是否自动转移
- 当主节点修复后,执行主从关系切换
- 做实验尽量贴合生成环境,尽量使用和生成环境一样数量的数据
- 评估和记录同步数据、故障转移完成的时间
- 当应用需要连接 redis cluster 集群时要将所有节点都写在配置文件中