Redis 哨兵模式
Redis 主从复制,无法解决自动进行主从切换的问题。哨兵模式就是为了解决这个问题的。Sentinel 负责持续监控 Redis 主从节点的健康状态,当主节点挂掉时,自动选择一个最优的从节点切换成为主节点。客户端来连接集群时,会首先连接 Sentinel,通过 Sentinel 来查询主节点的地址,然后再连接主节点进行数据交互。当主节点发生故障时,客户端会重新向 Sentinel 查询主节点地址,Sentinel 会将最新的主节点地址告诉客户端。
哨兵模式,无法保证数据不丢失,因为 Redis 主从采用异步复制,主节点挂掉时,无法保证从节点收到全部的同步消息。
Sentinel 提供如下功能:
- 监控:持续检测主从节点是否按预期工作。
- 通知:可通过 API 通知系统管理员或其他计算机程序,表明某个被监控的 Redis 实例出了问题。
- 自动故障转移:如果主节点未按预期工作,Sentinel 可以启动故障转移过程,将一个副本节点提升为主节点,其他额外的从节点被重新配置以使用新的主节点,并且使用 redis 服务器的应用会被告知连接时使用的新地址。
- 配置提供者:作为客户端服务发现的权威来源。
配置 sentinel.conf
bind 127.0.0.1 192.168.1.1 指定 redis 哨兵监听的网络接口,默认只监听 localhost。
protected-mode no 安全保护模式,no 允许来自任何主机的连接,yes 启用保护模式,只允许指定的连接。
port 26379 哨兵监听端口。
daemonize no 控制 sentinel 是否作为后台守护进程运行。no 在前台运行,yes 作为后台守护进程运行。容器化环境建议使用 no,前台运行可以让 docker 正确管理进程生命周期。
pidfile /var/run/redis-sentinel.pid 指定守护进程的 PID 文件路径。
logfile "" 指定日志文件路径。如果为空日志标准输出到 stdout。
sentinel announce-ip <ip> 配置 sentinel 对外通告的 IP 地址,当配置了这个地址时,哨兵将在 HELLO 消息中声明指定的 IP 地址,而不是自动检测本地地址。
sentinel announce-port <port> 配置 sentinel 对外通告的端口。
dir /tmp 工作目录,每个长时间运行的进程都应该有一个明确的工作目录,对于哨兵来说,在启动时将工作目录切换到 /tmp 是最简单的做法,这样可以避免进程干扰管理任务,例如卸载文件系统。
sentinel monitor <master-name> <ip> <redis-port> <quorum> 告诉 sentinel 监控这个主节点,并且只有在至少 <quorum 法定人数> 个 sentinel 同意的情况下才将其视为 O_DOWN 客观下线状态。无论客观下线的法定人数是多少,一个 Sentinel 都需要被已知 sentinel 中的大多数选举出来才能启动故障转移,因此无法在少数派中指定故障转移。哨兵会自动发现主节点的从节点,即从节点是自动发现的,因此不需要以任何方式指定从节点。Sentinel 本身将使用其他配置选项重写此配置文件来添加从节点。另外,当从节点被提升为主节点时,配置文件将被重写。
sentinel auth-pass <master-name> <password> 设置用于哨兵节点与主节点和从节点进行身份验证的密码。
sentinel auth-user <master-name> <username> 用于配置哨兵节点连接到受监控的 redis 主节点和从节点时使用的用户名,通常与 ACL 访问控制列表系统配合使用。
sentinel auth-pass 以及 sentinel auth-user 配置项,是哨兵节点作为客户端连接到主节点和从节点时使用的用户名以及密码。
sentinel down-after-milliseconds mymaster 30000 主节点(或任何连接的从节点或哨兵)应连续不可达(即对 PING 命令无有效回复)的毫秒数,以便将其视为处于 S_DOWN 状态(主观下线)。默认值为 30 秒。
主观下线(
S_DOWN)单个哨兵实例认为节点不可用 客观下线(O_DOWN)多个哨兵实例达成共识认为节点不可用
user <username> ... acl rules ... 配置 ACL,定义用户的状态、权限、密码等
acllog-max-len 128 配置 ACL 日志文件最大长度,当日志达到上限时,新的记录会覆盖最旧的记录。ACL 日志用于记录与 ACL 相关的失败命令和认证事件,存储在内存中,重启后丢失,可使用 ACL LOG RESET 命令回收内存。
aclfile /etc/redis/sentinel-users.acl 启用外部 ACL 文件,允许将用户 ACL 配置分离到独立文件。
requirepass <password> 设置 Sentinel 实例的认证密码,用于 Sentinel 实例之间相互认证,所有 Sentinel 实例都需要设置相同密码。当前建议使用 ACL 机制,requirepass 默认使用 default 用户。
sentinel sentinel-user <username> 配置 sentinel 实例之间相互认证时使用的用户名
sentinel sentinel-pass <password> 配置 sentinel 实例之间相互认证时使用的密码
sentinel parallel-syncs <master-name> <numreplicas> 在故障转移期间,我们可以同时重新配置多少个从节点指向新的主节点。如果从节点也用于处理读请求,则建议设为较低值,避免所有从节点同时不可用,保持查询服务能力。如果从节点不用于处理读请求,且希望尽快完成所有从节点同步,则可以设为较大值。
sentinel failover-timeout <master-name> <milliseconds> 指定故障转移超时时间:
- 同一个 Sentinel 对相同主节点再次启动故障转移所需的时间间隔,是故障转移超时时间的两倍。即第一次故障转移失败后,需要等待 2 倍的时间才能重试。
- 根据 Sentinel 当前配置,将复制错误主节点的从节点强制切换到正确主节点所需的时间,正好是故障转移超时时间。
- 取消一个已在进行中但未产生任何配置变更的故障转移所需的时间(已执行
SLAVEOF NO ONE但被提升的从节点尚未确认)。故障转移开始但被卡住无进展 -> 等待 milliseconds 时间超时 -> 取消故障转移 - 进行中的故障转移等待所有从节点被重新配置为新主节点从节点的最大时间。开始重配置所有副本 -> 等待 milliseconds 时间超时 -> 强制继续(忽略 parallel-syncs)
sentinel notification-script <master-name> <script-path> 通知脚本,在 Sentinel 检测到警告级别事件时触发,用于通知管理员(邮件、短信等)。
sentinel client-reconfig-script <master-name> <script-path> 客户端重配置脚本,在故障转移 failover 完成后触发,用于通知客户端主节点已变更(如更新客户端连接配置)。参数传递:<master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>,其中 from-ip:from-port 为旧主节点地址,<to-ip:to-port> 为新主节点地址。<state> 为 failover,role 为 leader 或 observer。
sentinel deny-scripts-reconfig yes 安全配置,禁止通过 sentinel set 命令动态修改脚本路径,防止恶意用户通过篡改脚本路径触发任意代码执行。启用后,必须直接修改 sentinel.conf 文件并重启 sentinel 服务才能更新脚本路径。
SENTINEL rename-command mymaster CONFIG GUESSME 命令重命名,在云服务或托管环境中,redis 实例的敏感命令(如 CONFIG、SLAVEOF)可能被重命名,以防止未经授权的操作。sentinel 依赖这些命令管理 redis 节点,因此需通过 sentinel rename-command 告知 sentinel 新的命令名称,否则 sentinel 将无法正常工作。仅对指定的节点生效,须在所有相关哨兵实例上配置相同规则。sentinel 依赖如下命令:
- CONFIG
- SLAVEOF
- INFO
- ROLE
- PING
必须确保以上命令被正确重命名。
SENTINEL resolve-hostnames no 是否启用主机名解析,设为 yes 后,sentinel 允许在配置中使用主机名。主机名支持配置解析,默认情况下,sentinel 仅支持使用 IP 地址进行节点监控与通信,在动态网络环境(如容器、云服务)中,节点 IP 可能频繁变化,使用主机名替代 IP 可提升配置灵活性,通过启用 resolve-hostnames 和 announce-hostnames 配置,sentinel 可支持主机名解析与公告,但需确保 DNS 配置可靠。
SENTINEL announce-hostnames no 是否在通信和日志中公告主机名,仅在 resolve-hostnames 为 yes 时生效。
哨兵示例
运行哨兵可以通过 redis-sentinel 命令启动。redis-sentinel /path/to/sentinel.conf。或者通过 redis-server /path/to/sentinel.conf --sentinel 启动。
配置示例:
# bind 127.0.0.1 192.168.1.1
# protected-mode no
port 26379
daemonize no
pidfile "/home/sl/redis/redis-sentinel.pid"
logfile ""
# sentinel announce-ip <ip>
# sentinel announce-port <port>
dir "/tmp"
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
# sentinel auth-pass <master-name> <password>
# sentinel auth-user <master-name> <username>
# sentinel down-after-milliseconds <master-name> <milliseconds>
acllog-max-len 128
sentinel deny-scripts-reconfig yes
sentinel resolve-hostnames no
sentinel announce-hostnames no
在搭建一主一从节点后,启动哨兵集群:
# 启动第一个哨兵
postgres@slpc:~/redis$ redis-sentinel sentinel.conf
5748:X 22 Oct 2025 13:53:27.472 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
5748:X 22 Oct 2025 13:53:27.472 # Redis version=6.2.18, bits=64, commit=ee4d13ab, modified=0, pid=5748, just started
5748:X 22 Oct 2025 13:53:27.472 # Configuration loaded
5748:X 22 Oct 2025 13:53:27.474 * Increased maximum number of open files to 10032 (it was originally set to 1024).
5748:X 22 Oct 2025 13:53:27.474 * monotonic clock: POSIX clock_gettime
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 6.2.18 (ee4d13ab/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 26379
| `-._ `._ / _.-' | PID: 5748
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | https://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
5748:X 22 Oct 2025 13:53:27.489 # Sentinel ID is 835b43912bcb0a5dd08d833aef340e97aa9237a8
5748:X 22 Oct 2025 13:53:27.489 # +monitor master mymaster 127.0.0.1 6379 quorum 2
5748:X 22 Oct 2025 13:53:27.490 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
# 启动第二个哨兵
postgres@slpc:~/redis$ redis-server sentinel2.conf --sentinel
5944:X 22 Oct 2025 14:03:31.297 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
5944:X 22 Oct 2025 14:03:31.297 # Redis version=6.2.18, bits=64, commit=ee4d13ab, modified=0, pid=5944, just started
5944:X 22 Oct 2025 14:03:31.297 # Configuration loaded
5944:X 22 Oct 2025 14:03:31.299 * Increased maximum number of open files to 10032 (it was originally set to 1024).
5944:X 22 Oct 2025 14:03:31.299 * monotonic clock: POSIX clock_gettime
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 6.2.18 (ee4d13ab/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 26380
| `-._ `._ / _.-' | PID: 5944
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | https://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
5944:X 22 Oct 2025 14:03:31.302 # Sentinel ID is 8a0fe5db2c44b9f2f2dbb316439940e48cfdbe82
5944:X 22 Oct 2025 14:03:31.302 # +monitor master mymaster 127.0.0.1 6379 quorum 2
5944:X 22 Oct 2025 14:03:31.303 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
5944:X 22 Oct 2025 14:03:32.809 * +sentinel sentinel 835b43912bcb0a5dd08d833aef340e97aa9237a8 127.0.0.1 26379 @ mymaster 127.0.0.1 6379
# 启动第三个哨兵
postgres@slpc:~/redis$ redis-sentinel sentinel3.conf
6112:X 22 Oct 2025 14:06:51.641 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
6112:X 22 Oct 2025 14:06:51.641 # Redis version=6.2.18, bits=64, commit=ee4d13ab, modified=0, pid=6112, just started
6112:X 22 Oct 2025 14:06:51.641 # Configuration loaded
6112:X 22 Oct 2025 14:06:51.644 * Increased maximum number of open files to 10032 (it was originally set to 1024).
6112:X 22 Oct 2025 14:06:51.644 * monotonic clock: POSIX clock_gettime
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 6.2.18 (ee4d13ab/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 26381
| `-._ `._ / _.-' | PID: 6112
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | https://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
6112:X 22 Oct 2025 14:06:51.649 # Sentinel ID is 689e2740152a2cd47744ebe6f78efe50c2a9005a
6112:X 22 Oct 2025 14:06:51.649 # +monitor master mymaster 127.0.0.1 6379 quorum 2
6112:X 22 Oct 2025 14:06:51.650 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
6112:X 22 Oct 2025 14:06:52.841 * +sentinel sentinel 835b43912bcb0a5dd08d833aef340e97aa9237a8 127.0.0.1 26379 @ mymaster 127.0.0.1 6379
6112:X 22 Oct 2025 14:06:53.107 * +sentinel sentinel 8a0fe5db2c44b9f2f2dbb316439940e48cfdbe82 127.0.0.1 26380 @ mymaster 127.0.0.1 6379
启动哨兵集群后,查看哨兵配置文件:
# Generated by CONFIG REWRITE
protected-mode no
user default on nopass ~* &* +@all
sentinel myid 835b43912bcb0a5dd08d833aef340e97aa9237a8
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 0
sentinel current-epoch 0
sentinel known-replica mymaster 127.0.0.1 6380
sentinel known-sentinel mymaster 127.0.0.1 26381 689e2740152a2cd47744ebe6f78efe50c2a9005a
sentinel known-sentinel mymaster 127.0.0.1 26380 8a0fe5db2c44b9f2f2dbb316439940e48cfdbe82
当主节点挂断时,哨兵会选择一个从节点提升为主节点。
5272:S 22 Oct 2025 14:31:05.932 # Connection with master lost.
5272:S 22 Oct 2025 14:31:05.932 * Caching the disconnected master state. # 检测到主节点断开连接
5272:S 22 Oct 2025 14:31:05.932 * Reconnecting to MASTER 127.0.0.1:6379 # 尝试重新连接主节点
5272:S 22 Oct 2025 14:31:05.932 * MASTER <-> REPLICA sync started
5272:S 22 Oct 2025 14:31:05.932 # Error condition on socket for SYNC: Connection refused
5272:S 22 Oct 2025 14:31:06.920 * Connecting to MASTER 127.0.0.1:6379
# ...
5272:S 22 Oct 2025 14:31:35.338 * MASTER <-> REPLICA sync started
5272:S 22 Oct 2025 14:31:35.338 # Error condition on socket for SYNC: Connection refused
5272:M 22 Oct 2025 14:31:36.294 * Discarding previously cached master state.
5272:M 22 Oct 2025 14:31:36.295 # Setting secondary replication ID to 14cb2814458f612a68f5d793131341893af1e20f, valid up to offset: 355634. New replication ID is 1a6ec8c82c1cf3d041aca7f21caa32a4d4d49565
# 将从节点提升为主节点
5272:M 22 Oct 2025 14:31:36.295 * MASTER MODE enabled (user request from 'id=7 addr=127.0.0.1:37586 laddr=127.0.0.1:6380 fd=11 name=sentinel-8a0fe5db-cmd age=1685 idle=0 flags=x db=0 sub=0 psub=0 multi=4 qbuf=188 qbuf-free=40766 argv-mem=4 obl=45 oll=0 omem=0 tot-mem=61468 events=r cmd=exec user=default redir=-1')
5272:M 22 Oct 2025 14:31:36.300 # CONFIG REWRITE executed with success.
此时哨兵节点日志:
5748:X 22 Oct 2025 14:31:35.992 # +sdown master mymaster 127.0.0.1 6379
5748:X 22 Oct 2025 14:31:36.079 # +new-epoch 1
5748:X 22 Oct 2025 14:31:36.081 # +vote-for-leader 8a0fe5db2c44b9f2f2dbb316439940e48cfdbe82 1
5748:X 22 Oct 2025 14:31:36.092 # +odown master mymaster 127.0.0.1 6379 #quorum 2/2
5748:X 22 Oct 2025 14:31:36.092 # Next failover delay: I will not start a failover before Wed Oct 22 14:37:36 2025
5748:X 22 Oct 2025 14:31:36.933 # +config-update-from sentinel 8a0fe5db2c44b9f2f2dbb316439940e48cfdbe82 127.0.0.1 26380 @ mymaster 127.0.0.1 6379
5748:X 22 Oct 2025 14:31:36.933 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380
5748:X 22 Oct 2025 14:31:36.933 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
5748:X 22 Oct 2025 14:32:06.974 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
此时,通过哨兵查询主节点:
127.0.0.1:26379> sentinel get-master-addr-by-name mymaster
1) "127.0.0.1"
2) "6380"
部署建议
实际部署时,建议在三台不同的服务器上部署至少 3 个哨兵。
+----+
| M1 |
| S1 | <- C1 (writes will be lost)
+----+
|
/
/
+------+ | +----+
| [M2] |----+----| R3 |
| S2 | | S3 |
+------+ +----+
网络分区情况考虑:在部署 3 节点时,如果网络分区隔离了旧主节点,如果客户端与旧主节点位于同一分区,那么客户端会继续向旧主节点写数据,这些数据会在分区恢复时,旧主节点将被重新配置为新主节点的从节点,丢弃其数据集。为了缓解此问题(注意不是解决),redis 可进行如下配置,该特性允许主节点在检测到无法将其写入传输到指定数量的副本节点时停止接收写入。
min-replicas-to-write 1 # 一个 redis 实例,如果无法写入至少 1 个从节点,将停止接受写入
min-replicas-max-lag 10 # 因此复制是异步的,无法写入实际上意味着该从节点要么已经断开连接,要么在超过指定的 max-lag 秒数后未向我们发送异步确认。这也是只能缓解问题,而不能解决的原因。
这种方法的弊端是,如果没有足够数量的从节点,主节点将无法写入数据,牺牲了可用性。
模拟主节点故障测试故障转移的方法:
redis-cli -p 6379 debug sleep 30
Sentinel 命令
SENTINEL CONFIG GET <name> (>= 6.2) 获取全局 Sentinel 配置参数的当前值。指定的名称可以是通配符,类似于 Redis 的 CONFIG GET 命令。
SENTINEL CONFIG SET <name> <value> (>= 6.2) 设置全局 Sentinel 配置参数的值。
SENTINEL CKQUORUM <master name> 检查当前的 Sentinel 配置是否能够达到故障转移主节点所需的仲裁数 (quorum),以及授权故障转移所需的大多数 (majority)。此命令应在监控系统中使用,以检查 Sentinel 部署是否正常。
127.0.0.1:26379> sentinel ckquorum mymaster
OK 3 usable Sentinels. Quorum and failover authorization can be reached
SENTINEL FLUSHCONFIG 强制 Sentinel 将其配置(包括当前 Sentinel 状态)重写到磁盘。通常,Sentinel 会在其状态发生变化时(指跨重启后持久化到磁盘的状态子集)重写配置。然而,有时由于操作错误、磁盘故障、软件包升级脚本或配置管理器,配置文件可能会丢失。在这种情况下,强制 Sentinel 重写配置文件的功能非常方便。此命令即使在之前的配置文件完全丢失的情况下也能工作。
SENTINEL FAILOVER <master name> 强制执行故障转移,就像主节点不可访问一样,且不询问其他 Sentinel 的同意(但是,将发布新版本的配置,以便其他 Sentinel 更新其配置)。
SENTINEL GET-MASTER-ADDR-BY-NAME <master name> 返回具有该名称的主节点的 IP 地址和端口号。如果此主节点正在进行故障转移或已成功完成,则返回被提升为新主节点的副本的地址和端口。
127.0.0.1:26379> sentinel get-master-addr-by-name mymaster
1) "127.0.0.1"
2) "6380"
SENTINEL INFO-CACHE (>= 3.2) 返回主节点和副本的缓存 INFO 输出。
SENTINEL IS-MASTER-DOWN-BY-ADDR 从当前 Sentinel 的角度检查指定 IP:Port 的主节点是否宕机。此命令主要用于内部使用。
SENTINEL MASTER <master name> 显示指定主节点的状态和信息。
SENTINEL MASTERS 显示被监控主节点的列表及其状态。
SENTINEL MONITOR 启动 Sentinel 的监控。有关详细信息,请参阅在运行时重新配置 Sentinel 部分。
SENTINEL MYID (>= 6.2) 返回 Sentinel 实例的 ID。
127.0.0.1:26380> sentinel myid
"8a0fe5db2c44b9f2f2dbb316439940e48cfdbe82"
SENTINEL PENDING-SCRIPTS 此命令返回有关待处理脚本的信息。
SENTINEL REMOVE 停止 Sentinel 的监控。有关详细信息,请参阅在运行时重新配置 Sentinel 部分。
SENTINEL REPLICAS <master name> (>= 5.0) 显示此主节点的副本列表及其状态。
SENTINEL SENTINELS <master name> 显示此主节点的 Sentinel 实例列表及其状态。
SENTINEL SET 设置 Sentinel 的监控配置。有关详细信息,请参阅在运行时重新配置 Sentinel 部分。
SENTINEL SIMULATE-FAILURE (crash-after-election|crash-after-promotion|help) (>= 3.2) 此命令模拟不同的 Sentinel 崩溃场景。
SENTINEL RESET <pattern> 此命令将重置所有匹配名称的主节点。pattern 参数是一个 glob 风格的模式。重置过程会清除主节点中的任何先前状态(包括正在进行的故障转移),并移除已发现并与该主节点关联的所有副本和 Sentinel。
sentinel 的 hello 命令,回复当前服务器和连接属性列表,例如:版本,已加载模块、客户端 ID 等。
127.0.0.1:26380> hello 3
1# "server" => "redis"
2# "version" => "6.2.18"
3# "proto" => (integer) 3
4# "id" => (integer) 5
5# "mode" => "sentinel"
6# "modules" => (empty array)
在运行时重新配置 Sentinel:
SENTINEL MONITOR <name> <ip> <port> <quorum>此命令告诉 Sentinel 开始监控一个新的主节点,指定其名称、IP、端口和仲裁数。它与 sentinel.conf 配置文件中的 sentinel monitor 配置指令相同,不同之处在于不能使用主机名作为 ip,而需要提供 IPv4 或 IPv6 地址。SENTINEL REMOVE <name>用于移除指定的主节点:该主节点将不再被监控,并会完全从 Sentinel 的内部状态中移除,因此将不再被 SENTINEL masters 等命令列出。SENTINEL SET <name> [<option> <value> ...]SET 命令与 Redis 的 CONFIG SET 命令非常相似,用于更改特定主节点的配置参数。可以指定多个选项/值对(也可以不指定)。所有可以通过 sentinel.conf 配置的配置参数也可以使用 SET 命令进行配置。
# 更改配置参数
127.0.0.1:26380> sentinel set mymaster down-after-milliseconds 1000
OK
# 更改主节点的仲裁数
127.0.0.1:26380> sentinel set mymaster quorum 2
OK
移除或者添加 Sentinel
Sentinel 是自发现机制,向部署添加新的哨兵实例非常简单,只需要在启动配置为监控当前活动主节点的新 Sentinel 即可。在 10 秒内,新 Sentinel 将获取其他 Sentinel 的列表以及连接到主节点的副本集合。如果需要一次添加多个 Sentinel 实例,建议一个接一个地添加,在添加下一个之前等待所有其他 sentinel 都已经知道第一个 sentinel,这有助于确保在添加新 sentinel 的过程中发生故障时,多数仍然只能在分区的一侧实现。建议在没有网络分区的情况下,每添加一个新 sentinel 实例间隔 30 秒。
移除 Sentinel 实例:Sentinel 从不忘记已经见过的 Sentinel,即使它们长时间不可访问。因此,在没有网络分区的情况下,应执行以下步骤来移除 Sentinel:
- 停止要移除的 Sentinel 实例。
- 向所有其他 Sentinel 实例发送
sentinel reset <mastername>命令(如果你只想重置单个主节点,可以使用精确的主节点名称代替*)。一个接一个地发送,实例之间至少等待 30 秒。 - 通过检查每个 Sentinel 的
sentinel master mastername命令的输出,确认所有 Sentinel 都对当前活动 Sentinel 的数量达成一致。
Sentinel 细节实现
SDOWN 和 ODOWN 状态
Sentinel 中有两种不同的”宕机”概念,一种称为主观宕机状态 SDOWN,这是某个 Sentinel 实例本地的宕机状态。另一种称为客观宕机状态 ODOWN,当足够多(至少是监控主节点配置的 quorum 参数指定的数量)的 Sentinel 处于 SDOWN 状态,并且通过 SENTINEL is-master-down-by-addr 命令从其他 Sentinel 获取反馈时,就达到了 ODOWN 状态。
从一个 Sentinel 的角度看,当它在配置中指定的 is-master-down-after-milliseconds 参数所指定的时间(秒)内没有收到 PING 请求的有效回复时,就达到了 SDOWN 状态。
VIP 切换
在 Redis 哨兵(Sentinel)高可用架构中,VIP(虚拟 IP)切换通常由外部脚本触发,当 Sentinel 检测到主节点故障并完成故障转移后,通过 sentinel notification-script 或 sentinel client-reconfig-script 通知外部系统,由脚本将 VIP 绑定到新的主节点上。
Client → VIP (192.168.1.100)
↓
[当前主节点:redis-node1 或 redis-node2]
Sentinel 集群监控主从状态
↓
主节点宕机 → Sentinel 选举新主 → 触发脚本 → 新主绑定 VIP/旧主解绑 VIP
(role)表示当前执行脚本的 Sentinel 节点在本次故障转移中的角色,有以下三种可能值:
| Role 值 | 含义 | 是否执行脚本? |
|---|---|---|
| leader | 该 Sentinel 是本次故障转移的领导者(Leader)→ 负责发起并完成 failover | ✅ 会执行 |
| observer | 该 Sentinel 是 观察者(Observer)→ 只监控,不参与选举,但知道结果 | ✅ 会执行 |
| sentinel | 普通 Sentinel(旧版本可能出现,新版本通常为 observer) | ✅ 会执行 |
✅ 结论:所有 Sentinel 节点在 failover 完成后都会执行 client-reconfig-script!需要注意的是
Redis Sentinel 是一个去中心化集群,每个 Sentinel 节点都独立运行,并通过 gossip 协议同步状态。
- 当 failover 完成后,所有 Sentinel 节点都会更新其内部对主库的认知
- 为了通知外部系统(如代理、客户端、VIP 管理器),每个 Sentinel 都会触发回调
- 这样设计是为了高可用和冗余:即使某个 Sentinel 宕机,其他节点仍能通知
所有哨兵节点都会执行该 VIP 脚本,但是哨兵节点不一定与 redis 主从节点在同一台主机上。
| 方案 | 说明 |
|---|---|
| ✅ 客户端直连 Sentinel | 应用通过 Sentinel 获取主地址(如 Jedis、Lettuce),无需 VIP |
| ✅ Keepalived + 自定义健康检查 | Keepalived 监控本地 Redis 是否为主,自动管理 VIP |
| ⚠️ Sentinel + 脚本 | 复杂,易出错,仅适合可控小规模环境 |