环境搭建

由于哨兵模式推荐至少 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-sentinels2,说明三个哨兵已经互相发现、组成集群,整个哨兵模式就配置完成了。

在这里插入图片描述


第六步:故障转移测试

故障转移的时间窗口如何体现出来?

在二号机开一个终端,持续轮询角色变化:

# 每隔 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
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐