Redis 主从复制详解:原理、配置与主从切换实战
Redis 主从复制详解:原理、配置与主从切换实战
在高并发场景下,单一 Redis 节点往往难以承受大量的读写请求。为了提高 Redis 的可用性和读写性能,主从复制(Master/Slave)架构成为了常用的解决方案。本文将详细介绍 Redis 主从复制的原理、配置方法以及主从切换的实战操作。
一、Redis 主从复制原理
Redis 主从复制是指将一台 Redis 服务器(主节点,Master)的数据复制到其他 Redis 服务器(从节点,Slave),数据复制是单向的,只能从主节点到从节点。
在实际应用中,通常使用一个 Master 节点处理写操作,多个 Slave 节点处理读操作,同时可以选择一个 Slave 节点进行数据备份,这样能最大程度发挥 Redis 的性能。需要注意的是,Master 和 Slave 的数据并非实时同步,但最终会达到一致,这就是最终一致性。
1.1 全量同步
全量同步是指从节点第一次连接主节点时,完整复制主节点所有数据的过程,具体步骤如下:
- Slave 发送 Sync 命令到 Master
- Master 启动后台进程,将 Redis 中的数据快照保存到文件中
- Master 将保存数据快照期间接收到的写命令缓存起来
- Master 完成文件写入后,将该文件发送给 Slave
- Slave 使用新接收的 RDB 或 AOF 文件替换旧文件
1.2 增量同步
增量同步用于网络中断等情况后的复制,只将中断期间主节点执行的写命令发送给从节点,比全量复制更高效。其实现依赖于三个重要概念:
(1)复制偏移量
主节点和从节点分别维护一个复制偏移量(offset),代表主节点向从节点传递的字节数。主节点每次向从节点传播 N 个字节数据时,自身 offset 增加 N;从节点每次收到 N 个字节数据时,自身 offset 也增加 N。通过比较两者的 offset,可以判断主从节点的数据是否一致。
(2)复制积压缓冲区
由主节点维护的固定长度 FIFO 队列,默认大小 1MB,当主节点有从节点时创建,用于备份主节点最近发送给从节点的数据。
在命令传播阶段,主节点会将写命令同时发送给从节点和复制积压缓冲区。由于缓冲区长度固定,当主从节点 offset 差距超过缓冲区长度时,将无法执行增量复制,只能执行全量复制。
可以通过配置repl-backlog-size
增大缓冲区大小,计算公式参考:网络中断平均时间 × 主节点每秒产生的写命令字节数 × 2(保险起见)。
(3)服务器运行 ID(runid)
每个 Redis 节点启动时会生成一个唯一的 40 位十六进制随机 ID,用于唯一识别节点。主从初次复制时,主节点将自己的 runid 发送给从节点,从节点保存该 runid。
当断线重连时,从节点将保存的 runid 发送给主节点:
- 如果 runid 相同,说明之前同步过,尝试进行增量复制
- 如果 runid 不同,说明从节点之前同步的不是当前主节点,只能进行全量复制
二、配置主从同步
2.1 环境说明
主机名 | IP 地址 | 角色 |
---|---|---|
redis-master | 192.168.2.20/24 | master |
redis-slave1 | 192.168.2.21/24 | slave1 |
redis-slave2 | 192.168.2.22/24 | slave2 |
2.2 配置 Master 节点
- 关闭防火墙和 SELinux
[root@redis-master ~]# systemctl disable --now firewalld
[root@redis-master ~]# setenforce 0
- 安装 Redis 并修改配置文件
[root@redis-master ~]# yum install redis -y
[root@redis-master ~]# vim /etc/redis/redis.conf
bind 0.0.0.0
protected-mode no
daemonize no #非后台运行
- 启动 Redis 并验证角色
[root@redis-master ~]# systemctl start redis
[root@redis-master ~]# redis-cli -p 6379
127.0.0.1:6379> info replication
role:master #当前角色为主
connected_slaves:0
master_failover_state:no-failover
master_replid:b765b9a92e508c2b912f56d2f496e34d1431818f
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
2.3 配置 Slave 节点
以 slave1 为例,slave2 配置类似:
- 关闭防火墙和 SELinux(同上)
- 安装 Redis 并修改配置文件
[root@redis-slave1 ~]# yum install redis -y
[root@redis-slave1 ~]# vim /etc/redis/redis.conf
bind 0.0.0.0
protected-mode no
daemonize no
replicaof 192.168.2.20 6379 #指定主节点地址和端口
- 临时配置主节点(无需重启 Redis,但重启后失效)
[root@redis-slave1 ~]# redis-cli -p 6379
127.0.0.1:6379> REPLICAOF 192.168.2.20 6379 #新版本
# 旧版本使用:slaveof 192.168.2.20 6379
OK
- 验证从节点配置
127.0.0.1:6379> info replication
# Replication
role:slave #当前从的角色调整为slave
master_host:192.168.2.20
master_port:6379
master_link_status:up
master_last_io_seconds_ago:2
master_sync_in_progress:0
slave_read_repl_offset:28
slave_repl_offset:28
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:80538ce104caeda1fc19a6e0f5292612e1805974
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:28
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:28
2.4 验证主从同步
- 在主节点添加数据
[root@redis-master ~]# redis-cli
127.0.0.1:6379> set master 192.168.2.20
OK
- 在从节点查看数据
[root@redis-slave1 ~]# redis-cli -p 6379
127.0.0.1:6379> get master
"192.168.2.20"
- 在主节点查看从节点连接情况
# 可以看到connected_slaves:2及两个从节点的信息
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.2.21,port=6379,state=online,offset=4421,lag=0
slave1:ip=192.168.2.22,port=6379,state=online,offset=4421,lag=0
master_failover_state:no-failover
master_replid:80538ce104caeda1fc19a6e0f5292612e1805974
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:4421
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:4421
三、主从切换实战
当主节点宕机后,需要将从节点提升为主节点,以保证服务继续运行。
3.1 模拟主节点宕机
[root@redis-master ~]# systemctl stop redis
3.2 将 slave1 提升为主节点
[root@redis-slave1 ~]# redis-cli
127.0.0.1:6379> REPLICAOF no one #新版本
# 旧版本使用:slaveof no one
OK# 验证角色已变为master
127.0.0.1:6379> info replication
# 可以看到role:master
3.3 将 slave2 重新指向新的主节点
[root@redis-slave2 ~]# redis-cli
127.0.0.1:6379> replicaof 192.168.2.21 6379 #新版本
# 旧版本使用:slaveof 192.168.2.21 6379
OK# 验证数据已同步
127.0.0.1:6379> get master
"192.168.2.21" #已更新为新主节点的数据
总结
Redis 主从复制通过将写操作集中在主节点,读操作分散到从节点,有效提高了 Redis 的并发处理能力。全量复制和增量复制机制保证了主从节点数据的最终一致性,而主从切换功能则提高了系统的可用性。
在实际生产环境中,除了手动进行主从切换,还可以结合 Redis Sentinel(哨兵)实现自动故障转移,进一步提高系统的稳定性和可靠性