Redis多哨兵模式

多哨兵模式

方案1:Redis-0为哨兵并在其中设置三个哨兵sentinel-1.conf、sentinel-2.conf、sentinel-3.conf

方案2:在Redis-1为主机,Redis-2、Redis-3为从机,里面各设置一个哨兵

方案3:Redis-1为主机,Redis-2、Redis-3为从机,Redis-11/Redis-22/Redis-33为哨兵

不推荐方案1:这是典型的“伪高可用”。把3个哨兵进程放在同一台机器(Redis-0)上,这台机器一旦宕机(比如断电、网络断开),3个哨兵会同时离线(可作为测试或实验操作)

推荐方案2:生产环境最常用的方案,强烈推荐。

推荐方案3:(3台Redis机器 + 3台独立哨兵机器)可靠性最高的方案,但成本也最高。

设置哨兵

前置条件

搭建好主从环境、设置环境变量,在操作哨兵设置

配置哨兵文件

 # 进入文件目录
 cd /usr/local/src/redis-6.2.14
 ​
 # 过滤并生成精简配置文件
 grep -E -v "^$|^#" sentinel.conf > /usr/local/redis/etc/sentinel.conf
 ​
 # 切换目录
 cd  /usr/local/redis/etc/
 ​
 # 修改哨兵配置文件
 vim sentinel.conf

主节点哨兵(192.168.7.81)

 # 基础配置
 port 26379
 bind 192.168.7.81
 protected-mode yes
 daemonize yes
 pidfile /var/run/redis-sentinel.pid
 logfile "/usr/local/redis/logs/sentinel.log"
 dir "/usr/local/redis/sentinel-data"
 ​
 # 监控主节点(注意:这里仍然写主节点IP,不是本机IP!)
 sentinel monitor mymaster 192.168.7.81 6379 2
 sentinel down-after-milliseconds mymaster 30000
 sentinel parallel-syncs mymaster 1
 sentinel failover-timeout mymaster 180000
 ​
 acllog-max-len 128
 sentinel deny-scripts-reconfig yes
 sentinel resolve-hostnames no
 sentinel announce-hostnames no
 sentinel announce-ip 192.168.7.81
 ​
 注意:
 如果设置密码需要添加
 sentinel auth-pass mymaster 密码

从节点1哨兵(192.168.7.82)

 # 基础配置
 port 26379
 bind 192.168.7.82
 protected-mode yes
 daemonize yes
 pidfile /var/run/redis-sentinel.pid
 logfile "/usr/local/redis/logs/sentinel.log"
 dir "/usr/local/redis/sentinel-data"
 ​
 # 监控主节点(注意:这里仍然写主节点IP,不是本机IP!)
 sentinel monitor mymaster 192.168.7.81 6379 2
 sentinel down-after-milliseconds mymaster 30000
 sentinel parallel-syncs mymaster 1
 sentinel failover-timeout mymaster 180000
 ​
 acllog-max-len 128
 sentinel deny-scripts-reconfig yes
 sentinel resolve-hostnames no
 sentinel announce-hostnames no
 sentinel announce-ip 192.168.7.82
 ​
 注意:
 如果设置密码需要添加
 sentinel auth-pass mymaster 密码

从节点2哨兵(192.168.7.83)

 # 基础配置
 port 26379
 bind 192.168.7.83
 protected-mode yes
 daemonize yes
 pidfile /var/run/redis-sentinel.pid
 logfile "/usr/local/redis/logs/sentinel.log"
 dir "/usr/local/redis/sentinel-data"
 ​
 # 监控主节点(注意:这里仍然写主节点IP,不是本机IP!)
 sentinel monitor mymaster 192.168.7.81 6379 2
 sentinel down-after-milliseconds mymaster 30000
 sentinel parallel-syncs mymaster 1
 sentinel failover-timeout mymaster 180000
 ​
 acllog-max-len 128
 sentinel deny-scripts-reconfig yes
 sentinel resolve-hostnames no
 sentinel announce-hostnames no
 sentinel announce-ip 192.168.7.83
 ​
 注意:
 如果设置密码需要添加
 sentinel auth-pass mymaster 密码

启动Redis和哨兵

先启动Redis

 # 启动Redis服务
 redis-server /usr/local/redis/etc/redis.conf
 ​
 # 启动客户端
 redis-cli -h 127.0.0.1 -p 6379
 ​
 # 如果设置密码需要添加 -a 密码
 redis-cli -h 127.0.0.1 -p 6379 -a 123456
 ​
 # 或进入客户端后在验证密码
 redis-cli -h 127.0.0.1 -p 6379
 127.0.0.1:7000> AUTH 123456
 ​
 # 验证主从连接
 redis-cli -h 192.168.7.81 -p 6379
 > info replication

在启动哨兵

 # 启动哨兵
 redis-sentinel /usr/local/redis/etc/sentinel.conf
 ​
 # 实时查看哨兵日志
 tail -f /usr/local/redis/logs/sentinel.log

查看哨兵连接状态

 # 查看主节点信息
 redis-cli -h 192.168.7.81 -p 26379 sentinel master mymaster
 ​
 # 查看所有从节点
 redis-cli -h 192.168.7.81 -p 26379 sentinel slaves mymaster
 ​
 # 查看所有哨兵
 redis-cli -h 192.168.7.81 -p 26379 sentinel sentinels mymaster
 ​
 # 查看集群概要
 redis-cli -h 192.168.7.81 -p 26379 info sentinel

模拟宕机

模拟从机宕机

杀死Redis-2从机进程,30秒后观察哨兵日志

注意:如果设置自启日志可能只会显示重启,解决方案在下面。

 # 查看服务进程
 ps -ef|grep redis
 ​
 # 显示服务进程
 root        5078       1  0 20:20 ?        00:00:05 /usr/local/redis/bin/redis-server 0.0.0.0:6379
 root        5521    4867  0 20:59 pts/0    00:00:00 grep --color=auto redis
 ​
 # 强制关闭服务进程
 kill -s 9 5078
 ​
 # 实时查看哨兵日志
 tail -f /var/log/redis/sentinel.log

启动Redis-2从机,观察哨兵日志

 redis-server /usr/local/redis/etc/redis.conf

日志状态及解读

 09:30:10.071 # +sdown slave 192.168.7.72   # 1. 哨兵发现从库挂了(主观下线)
 09:31:29.078 * +reboot slave 192.168.7.72  # 2. 从库进程重新启动,哨兵检测到了
 09:31:29.121 # -sdown slave 192.168.7.72   # 3. 哨兵确认从库已恢复,解除下线标记

模拟主机宕机

杀死Redis-1主机进程,30秒后观察哨兵日志

注意:如果设置自启日志可能只会显示重启,解决方案在下面。

 # 查看服务进程
 ps -ef|grep redis
 ​
 # 显示服务进程
 root        1109       1  0 08:20 ?        00:00:09 /usr/local/redis/bin/redis-server 0.0.0.0:6379
 root        3353    2554  0 09:02 pts/0    00:00:00 grep --color=auto redis
 ​
 # 强制关闭服务进程
 kill -s 9 1109

启动Redis-1主机,观察哨兵日志

 redis-server /usr/local/redis/etc/redis.conf

日志状态解读

 # 关闭主库后的日志
 09:34:17.542 # +sdown master 192.168.7.71                 # 1. 哨兵发现主库挂了(主观下线)
 09:34:17.544 # +odown master 192.168.7.71                   # 2. 客观下线,触发故障转移
 09:34:17.544 # +new-epoch 4                                 # 3. 开启新纪元
 09:34:17.544 # +try-failover master 192.168.7.71            # 4. 尝试发起故障转移
 09:34:17.552 # +vote-for-leader 0318d09a...                 # 5. 投票给 Leader
 09:34:17.552 # +elected-leader master 192.168.7.71          # 6. 当选 Leader
 09:34:17.552 # +failover-state-select-slave                 # 7. 开始挑选从库
 09:34:17.615 # +selected-slave 192.168.7.73                 # 8. 选中 7.73 作为新主
 09:34:17.615 * +failover-state-send-slaveof-noone           # 9. 提升 7.73 为主库
 09:34:17.668 * +failover-state-wait-promotion               # 10. 等待提升完成
 09:34:18.582 # +promoted-slave 192.168.7.73                 # 11. 7.73 已升为主库
 09:34:18.582 # +failover-state-reconf-slaves                # 12. 重新配置其他从库
 09:34:18.629 * +slave-reconf-sent 192.168.7.72              # 13. 向 7.72 发送同步命令
 09:34:18.904 * +slave-reconf-inprog 192.168.7.72            # 14. 7.72 正在同步数据
 09:34:18.905 * +slave-reconf-done 192.168.7.72              # 15. 7.72 同步完成
 09:34:18.963 # +failover-end master 192.168.7.71            # 16. 故障转移结束
 09:34:18.963 # +switch-master 7.71→7.73                     # 17. 🎯 主库切换完成
 09:34:18.964 * +slave 192.168.7.72                          # 18. 7.72 确认为从库
 09:34:18.964 * +slave 192.168.7.71                          # 19. 原主 7.71 被加为从库
 09:34:48.968 # +sdown slave 192.168.7.71                  # 20. 原主未启动,哨兵检测为下线
 ​
 # 开启原主库后的日志
 09:43:53.989 # -sdown slave 192.168.7.71              # 1. 哨兵确认原主已启动,解除下线标记
 09:44:03.956 * +convert-to-slave slave 192.168.7.71   # 2. 原主库自动降级为从库,加入集群

设置开机自启

添加systemctl启动项

 # 编辑配置文件
 vim /etc/systemd/system/redis.service
 ​
 # 添加以下内容
 [Unit]
 Description=Redis 6379 - Production Server
 After=network.target
 Wants=network-online.target
 ​
 [Service]
 Type=forking
 PIDFile=/run/redis_6379.pid
 ​
 # 启动 Redis
 ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf
 ​
 # 启动后检查 PID 文件是否生成(最多等待 2 秒)
 ExecStartPost=/bin/bash -c 'for i in {1..20}; do [ -f /run/redis_6379.pid ] && exit 0; sleep 0.1; done; exit 1'
 ​
 # 优雅关闭 Redis(假设无密码,如有密码需加 -a)
 ExecStop=/usr/local/redis/bin/redis-cli shutdown
 ​
 # 重载配置(将运行时配置持久化到文件)
 ExecReload=/usr/local/redis/bin/redis-cli CONFIG REWRITE
 ​
 # 重启策略:非正常退出时重启,等待 5 秒防止频繁重启
 Restart=on-failure
 RestartSec=5s
 ​
 # 资源限制:防止 OOM 或 FD 耗尽
 LimitNOFILE=65536
 LimitNPROC=65536
 ​
 # 超时控制:避免卡死时无限等待
 TimeoutStartSec=10s
 TimeoutStopSec=30s
 ​
 [Install]
 WantedBy=multi-user.target

设置刷新配置和启动服务

 # 重新加载 systemd
 systemctl daemon-reload
 ​
 # 停掉当前手动运行的 Redis
 pkill redis-server
 ​
 # 用 systemctl 启动
 systemctl start redis
 ​
 # 设置开机自启
 systemctl enable redis
 ​
 # 检查状态
 systemctl status redis

设置哨兵自启

编辑配置文件并写入

 # 编辑配置文件
 vim /etc/systemd/system/redis-sentinel.service
 ​
 # 写入以下内容
 [Unit]
 Description=Redis Sentinel 26379 - Production High Availability
 After=network.target
 Wants=network-online.target
 ​
 [Service]
 Type=forking
 PIDFile=/var/run/redis-sentinel.pid
 ​
 ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/etc/sentinel.conf --sentinel
 ExecStartPost=/bin/bash -c 'for i in {1..30}; do [ -f /run/redis-sentinel.pid ] && exit 0; sleep 0.1; done; exit 1'
 ExecStop=/usr/local/redis/bin/redis-cli -p 26379 shutdown
 ExecReload=/bin/kill -HUP $MAINPID
 ​
 Restart=on-failure
 RestartSec=10s
 ​
 LimitNOFILE=65536
 LimitNPROC=65536
 ​
 TimeoutStartSec=15s
 TimeoutStopSec=30s
 ​
 StandardOutput=syslog
 StandardError=syslog
 SyslogIdentifier=redis-sentinel
 ​
 [Install]
 WantedBy=multi-user.target

重载 systemd 并设置开机自启

 # 重新加载系统服务配置
 systemctl daemon-reload
 ​
 # 启动哨兵服务
 systemctl start redis-sentinel
 ​
 # 设置开机自动启动
 systemctl enable redis-sentinel
 ​
 # 查看服务状态(确认 Active 为 running,且 Enabled 为 enabled)
 systemctl status redis-sentinel

如果设置密码了

 [Unit]
 Description=Redis Sentinel 26379 - Production High Availability
 After=network.target
 Wants=network-online.target
 ​
 [Service]
 Type=forking
 PIDFile=/var/run/redis-sentinel.pid
 ​
 ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/etc/sentinel.conf --sentinel
 ExecStartPost=/bin/bash -c 'for i in {1..30}; do [ -f /run/redis-sentinel.pid ] && exit 0; sleep 0.1; done; exit 1'
 ExecStop=/usr/local/redis/bin/redis-cli -p 26379 -a 123456 shutdown
 ExecReload=/bin/kill -HUP $MAINPID
 ​
 Restart=on-failure
 RestartSec=10s
 ​
 LimitNOFILE=65536
 LimitNPROC=65536
 ​
 TimeoutStartSec=15s
 TimeoutStopSec=30s
 ​
 StandardOutput=syslog
 StandardError=syslog
 SyslogIdentifier=redis-sentinel
 ​
 [Install]
 WantedBy=multi-user.target