Redis 集群搭建:主从复制 +哨兵模式(Ubuntu 系统)
环境搭建
由于哨兵模式推荐至少 3 个哨兵节点以保证选举仲裁(quorum),在两台机器的条件下,我们采用如下布局:
| 机器 | IP | 角色 |
|---|---|---|
| 一号机 | 159.75.x.x | Redis Master(6379)+ Sentinel-1(26379) |
| 二号机 | 134.175.x.x | Redis Slave(6379)+ Sentinel-2(26379)+ Sentinel-3(26380) |
哨兵数为 3,quorum 设为 2,满足多数派原则。
第一步:环境准备(两台机器均执行)
安装 Redis
# CentOS / TencentOS
sudo yum install -y redis
# Ubuntu
sudo apt update && sudo apt install -y redis-server
关闭防火墙或放通端口
在腾讯云-安全组中,两台机器互相放通以下入站端口
6379 # Redis 主从通信
26379 # Sentinel-1 / Sentinel-2
26380 # Sentinel-3(二号机专用)
建议来源 IP 只填写两台机器的内网 IP,不要对公网全放开。
第二步:配置 Redis Master(一号机:159.75.x.x)
编辑 /etc/redis/redis.conf(或 /etc/redis.conf):
sudo vim /etc/redis/redis.conf
# 监听所有网卡(或指定内网 IP)
bind 0.0.0.0
# 端口
port 6379
# 后台运行
daemonize yes
# 日志与持久化
logfile "/var/log/redis/redis-master.log"
dir /var/lib/redis
# 设置访问密码(主从密码需一致)
requirepass yourRedisPassword
# 允许从节点连接时使用的密码
masterauth yourRedisPassword
启动并设置开机自启:
sudo systemctl restart redis
sudo systemctl enable redis
注意:restart 一定要成功,看到更新时间。
这里是 6s ago

第三步:配置 Redis Slave(二号机)
编辑 /etc/redis/redis.conf:
bind 0.0.0.0
port 6379
daemonize yes
logfile "/var/log/redis/redis-slave.log"
dir /var/lib/redis
# 指向 Master
replicaof 159.75.x.x 6379
# 连接 Master 的密码
masterauth yourRedisPassword
# 本机访问密码
requirepass yourRedisPassword
# 从节点只读
replica-read-only yes
启动:
sudo systemctl restart redis
sudo systemctl enable redis
验证主从同步
验证主从关系是否生效
在一号机执行:
redis-cli -a yourRedisPassword info replication
验证写入数据是否同步
root@VM-0-8-ubuntu:~# redis-cli
127.0.0.1:6379> AUTH xxxxxx
OK
127.0.0.1:6379> set user_id 123456
OK
127.0.0.1:6379> get user_id
(nil)
127.0.0.1:6379> get user_id
"123456"
验证从节点是否只读
127.0.0.1:6379> set user_id_1 liguojun
(error) READONLY You can't write against a read only replica.
127.0.0.1:6379>

验证实时同步(动态观察)
二号机开一个终端,持续监听所有命令:
root@VM-0-8-ubuntu: redis-cli -a {yourPassword} -h 127.0.0.1 -p 6379 monitor
一号机在另一个终端写入新数据:
root@VM-0-13-ubuntu: redis-cli -a {yourPassword} SET realtime:key "$(date '+%Y-%m-%d %H:%M:%S')"
二号机的 monitor 窗口应该实时出现来自 Master 的同步命令,类似:
1775650304.962845 [0 159.75.x.x:6379] "SET" "realtime:key" "2026-04-08 20:11:44"
第五步:查看主从偏移量是否一致(最严谨的方式)
# 一号机执行
redis-cli -a xxxxx info replication | grep -E "master_repl_offset|slave0"
# 二号机执行
redis-cli -a xxxxx info replication | grep -E "master_repl_offset|slave_repl_offset"
对比两边的 offset 值:
# 一号机输出
master_repl_offset:1024
slave0:ip=134.175.x.x,port=6379,state=online,offset=1024,lag=0
# 二号机输出
master_repl_offset:1024 # ← 和主节点相同,说明完全同步,无数据丢失
lag=0 且两边 offset 相同,代表主从之间零延迟、完全一致。
第四步:配置哨兵
sentinel 不需要独立安装,Redis 自带。redis-sentinel 就是 redis-server 的一个别名/软链接,安装 Redis 的时候已经一起装好了。
一号机 — Sentinel-1(端口 26379)
创建 /etc/redis/sentinel-1.conf:
# 一号机创建 sentinel-1.conf
sudo touch /etc/redis/sentinel-1.conf
sudo chown redis:redis /etc/redis/sentinel-1.conf
写入内容
sudo tee /etc/redis/sentinel-1.conf > /dev/null << 'EOF'
port 26379
daemonize yes
logfile "/var/log/redis/sentinel-1.log"
dir /var/lib/redis
sentinel monitor mymaster 159.75.x.x 6379 2 # 表示需要 2 个 Sentinel达成一致
sentinel auth-pass mymaster ${your_password}
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
EOF
确认写入成功
cat /etc/redis/sentinel-1.conf
启动哨兵:
redis-server /etc/redis/sentinel-1.conf --sentinel
检查是否启动成功:
ps -ef | grep redis-server

想要重启的话:
kill -9 ${pid}
redis-server /etc/redis/sentinel-1.conf --sentinel
ps -ef | grep redis-server
二号机 — Sentinel-2(端口 26379)
创建 /etc/redis/sentinel-2.conf:
sudo touch /etc/redis/sentinel-2.conf
sudo chown redis:redis /etc/redis/sentinel-2.conf
sudo tee /etc/redis/sentinel-2.conf > /dev/null << 'EOF'
port 26379
daemonize yes
logfile "/var/log/redis/sentinel-2.log"
dir /var/lib/redis
sentinel monitor mymaster 159.75.x.x 6379 2
sentinel auth-pass mymaster ${your_password}
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
EOF
二号机 — Sentinel-3(端口 26380)
创建 /etc/redis/sentinel-3.conf:
sudo touch /etc/redis/sentinel-3.conf
sudo chown redis:redis /etc/redis/sentinel-3.conf
sudo tee /etc/redis/sentinel-3.conf > /dev/null << 'EOF'
port 26380
daemonize yes
logfile "/var/log/redis/sentinel-3.log"
dir /var/lib/redis
sentinel monitor mymaster 159.75.x.x 6379 2
sentinel auth-pass mymaster ${your_password}
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
EOF
在二号机上同时启动两个哨兵:
redis-server /etc/redis/sentinel-2.conf --sentinel
redis-server /etc/redis/sentinel-2.conf --sentinel
检查两个哨兵的启动情况
ps -ef | grep redis-server

第五步:验证哨兵状态
在任意一台机器执行:
redis-cli -p 26379 sentinel masters
关键字段确认:
如果 num-other-sentinels 是 2,说明三个哨兵已经互相发现、组成集群,整个哨兵模式就配置完成了。

第六步:故障转移测试
故障转移的时间窗口如何体现出来?
在二号机开一个终端,持续轮询角色变化:
# 每隔 1 秒轮询一次,打印时间戳和当前角色
while true; do
ROLE=$(redis-cli -a ${your_password} -p 6379 info replication 2>/dev/null | grep "^role" | tr -d '\r')
echo "$(date '+%H:%M:%S') → $ROLE"
sleep 1
done
然后在一号机停掉 Redis:
sudo systemctl stop redis
你会看到二号机的轮询输出:
从节点在master挂了之后,还输出了几次**role:slave**,所以是有时间窗口的。
原来 Master 恢复后会变成 Slave吗?
是的,原 Master 恢复后会自动降级为 Slave。
原 Master 重新上线
↓
哨兵检测到它恢复(+reboot master)
↓
哨兵向它发送:REPLICAOF 134.175.x.x 6379
↓
原 Master 变成新 Master 的 Slave
↓
集群恢复为 1master + 1slave 状态
在一号机重启 Redis 之后
# 一号机重启
sudo systemctl start redis
# 等待 5 秒后,分别在两台机器查询角色
# 一号机
redis-cli -a xxxxx info replication | grep role
# 二号机
redis-cli -a xxxxx info replication | grep role
⚠️ 这就是为什么一号机的 redis.conf 里也必须配置 masterauth,因为它随时可能变成 Slave 去连接新 Master。
redis.conf 配置文件什么时候被修改
故障转移完成后,**二号机的 ****/etc/redis/redis.conf** 会被哨兵自动修改:
# 故障转移前(原始内容)
replicaof 159.75.x.x 6379
# 故障转移后(哨兵自动修改,这一行被 删除)
# replicaof 这行消失了,因为它已经是 master

一号机重新上线后,哨兵会向它写入新的复制指向,**/etc/redis/redis.conf** 会被追加:
# 哨兵自动追加这一行,指向新 master
replicaof 134.175.x.x 6379
每次故障转移,三个 sentinel.conf 都会被自动改写,更新记录的 master IP:
# 故障转移前
sentinel monitor mymaster 159.75.x.x 6379 2
# 故障转移后(自动更新为新 master 的 IP)
sentinel monitor mymaster 134.175.x.x 6379 2
在原 master 节点上面执行写入操作,就会被拒绝。
127.0.0.1:6379> set username liguojun
(error) READONLY You can't write against a read only replica.

SpringBoot 连接 Redis 集群(可选)
SpringBoot 不应该再直连某一台 Redis 主节点。
SpringBoot 不能直连 Redis 服务节点,因为主从切换会出问题。
spring:
redis:
host: 192.168.1.10
port: 6379
这其实就是告诉 SpringBoot:
“你只连 192.168.1.10:6379 这一台。”
问题在于:
- 正常时,这台可能是主节点,读写都没问题
- 发生故障后,哨兵会把别的从节点提升为新的主节点
- 但你的 SpringBoot 还在连旧地址
- 旧地址现在可能已经是从节点了
- Redis 从节点不能执行写命令,就会出现类似错误
READONLY You can't write against a read only replica
SpringBoot 应该如何连接集群
spring:
redis:
password: 123456 # Redis 密码
database: 0 # 使用第 0 个库
timeout: 5000ms # 连接超时时间
sentinel:
master: mymaster # 哨兵监控的主节点名称
nodes:
- 192.168.1.101:26379 # 哨兵节点1
- 192.168.1.102:26379 # 哨兵节点2
- 192.168.1.103:26379 # 哨兵节点3
注意:master: mymaster 不是随便写的,也不是 SpringBoot 自定义的,而是必须和 Sentinel 配置里的名称完全一致。 在 Sentinel 配置文件 **sentinel.conf** 中
# sentinel monitor <主节点名称> <IP> <端口> <quorum>
sentinel monitor mymaster 192.168.1.10 6379 2
所以在 SpringBoot 项目中,application.yaml 应该这样配置 Redis 主从集群
spring:
data:
redis:
password: {password} # Redis 密码
database: 0 # Redis 数据库编号
timeout: 5s # 连接超时时间
lettuce:
pool:
max-active: 16 # 最大连接数
max-idle: 8 # 最大空闲连接数
min-idle: 2 # 最小空闲连接数
max-wait: 3s # 获取连接最大等待时间
sentinel:
master: mymaster # Sentinel 配置文件中:监控的主节点名称
nodes:
- ip:port # 哨兵节点1
- ip:port # 哨兵节点2
- ip:port # 哨兵节点3
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)