IT策士 10余年一线大厂经验专注 IT 思维、架构、职场进阶。我会在各个平台持续发布最新文章助你少走弯路。上一篇我们搭建了 Redis 主从架构实现了数据冗余和读写分离。但有个致命问题当主节点宕机时必须手动将某个从节点提升为主节点再通知其他从节点和所有应用修改连接地址。这个过程少则几分钟多则半小时对于核心业务来说完全不可接受。Redis Sentinel哨兵就是为解决这个问题而生的。它能自动监控主从节点、自动发现故障、自动完成故障转移让 Redis 真正具备生产级高可用能力。本文带你从原理到实战用 Docker 搭建完整哨兵集群并用 Python 客户端对接感受自动故障转移的丝滑体验。1. Sentinel 是什么解决了什么问题Sentinel 是一套独立的分布式监控系统它由多个哨兵进程组成共同协作完成三个核心任务监控Monitoring持续检查主节点和从节点是否正常运行。通知Notification当节点状态发生变化时通过 API 或脚本通知管理员和其他应用。自动故障转移Automatic Failover当主节点不可用时自动选举一个从节点升级为新主节点并让其他从节点和新主节点同步。架构图┌──────────────┬──────────────┬──────────────┐ │ Sentinel1│ Sentinel2│ Sentinel3│ ← 哨兵集群至少3个 └──────┬───────┴──────┬───────┴──────┬───────┘ │ │ │ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Master │───│ Slave1│ │ Slave2│ └──────────┘ └──────────┘ └──────────┘ Sentinel 本身不存储数据它是独立于 Redis 数据节点的控制平面。即使没有 SentinelRedis 也能正常工作加上 Sentinel就拥有了自动化的“守护神”。2. 核心原理主观下线与客观下线哨兵判断一个节点是否故障用了两层机制。2.1 主观下线SDOWN每个哨兵进程每隔 1 秒向主节点、从节点、其他哨兵发送PING命令。如果某个节点在down-after-milliseconds配置项默认 30 秒时间内没有有效回复这个哨兵自身就会标记该节点为主观下线Subjectively Down。但单个哨兵的判断可能失误——比如自己的网络出了故障。所以不能仅凭 SDOWN 就发起故障转移。2.2 客观下线ODOWN当某个哨兵发现主节点进入 SDOWN 后它会询问其他哨兵“你们也觉得主节点挂了吗” 当达到quorum法定人数通常为哨兵数量的半数以上个哨兵都认为主节点下线该节点就被标记为客观下线Objectively Down。此时哨兵集群会通过Raft 算法选举出一个哨兵领导者由它来执行故障转移。2.3 故障转移流程哨兵领导者从所有健康的从节点中按优先级、复制偏移量、runid 等规则选出最合适的一个。向被选中的从节点发送SLAVEOF NO ONE将其提升为主节点。向其他从节点发送SLAVEOF 新主IP 新主端口让它们同步新主。将旧主节点的地址更新到哨兵配置中一旦旧主恢复它将成为新主的从节点。整个过程通常在10~30 秒内完成。⚠️ Sentinel 只对主节点做客观下线判断。从节点和哨兵节点只需要主观下线即可做出反应。3. 关键配置参数详解在开始实战之前先理解 Sentinel 的核心配置项# sentinel.conf 核心配置# 监控的主节点名称、IP、端口、quorum法定人数sentinel monitor mymaster127.0.0.163792# 主观下线判定超时毫秒超过此时间无响应则 SDOWNsentinel down-after-milliseconds mymaster5000# 故障转移最大超时毫秒超过此时间未完成则重新选举领导者sentinel failover-timeout mymaster10000# 新主节点同步时允许同时同步的从节点数量越小同步越慢但主节点压力小sentinel parallel-syncs mymaster1# 哨兵端口port26379quorum 建议3 个哨兵设quorum25 个哨兵设quorum3。这保证即使少数哨兵故障也能正常完成故障转移。4. 实战Docker 搭建 Sentinel 集群我们搭建一个“1 主 2 从 3 哨兵”的完整环境。4.1 整体架构Sentinel 集群26379/26380/26381 │ ▼ 主节点 Master6379 │ ┌───┴───┐ ▼ ▼ Slave16380 Slave263814.2 创建网络和主从节点# 创建网络dockernetwork create sentinel-net# 启动主节点dockerrun-d--nameredis-master--networksentinel-net\-p6379:6379 redis:7.2 redis-server--appendonlyyes# 启动从节点 1dockerrun-d--nameredis-slave1--networksentinel-net\-p6380:6379 redis:7.2 redis-server\--appendonlyyes--slaveofredis-master6379# 启动从节点 2dockerrun-d--nameredis-slave2--networksentinel-net\-p6381:6379 redis:7.2 redis-server\--appendonlyyes--slaveofredis-master6379验证主从状态dockerexecredis-master redis-cli INFO replication|grepconnected_slaves# connected_slaves:24.3 配置并启动 3 个哨兵首先在宿主机创建哨兵配置文件3 份# 创建目录mkdir-p~/sentinel/conf# 哨兵配置文件cat~/sentinel/conf/sentinel.confEOF port 26379 dir /data sentinel monitor mymaster redis-master 6379 2 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 10000 sentinel parallel-syncs mymaster 1 EOF# 复制为 3 份端口不同cp~/sentinel/conf/sentinel.conf ~/sentinel/conf/sentinel1.confcp~/sentinel/conf/sentinel.conf ~/sentinel/conf/sentinel2.confcp~/sentinel/conf/sentinel.conf ~/sentinel/conf/sentinel3.conf⚠️ 实际生产中 3 个哨兵最好部署在不同物理机上这里仅演示原理都放在同一台机器。启动哨兵容器# 哨兵 1 (端口 26379)dockerrun-d--namesentinel1--networksentinel-net\-p26379:26379\-v~/sentinel/conf/sentinel1.conf:/etc/redis/sentinel.conf\redis:7.2 redis-sentinel /etc/redis/sentinel.conf# 哨兵 2 (端口 26380)dockerrun-d--namesentinel2--networksentinel-net\-p26380:26379\-v~/sentinel/conf/sentinel2.conf:/etc/redis/sentinel.conf\redis:7.2 redis-sentinel /etc/redis/sentinel.conf# 哨兵 3 (端口 26381)dockerrun-d--namesentinel3--networksentinel-net\-p26381:26379\-v~/sentinel/conf/sentinel3.conf:/etc/redis/sentinel.conf\redis:7.2 redis-sentinel /etc/redis/sentinel.conf4.4 验证哨兵状态连接到任意哨兵查看信息dockerexec-itsentinel1 redis-cli-p26379127.0.0.1:26379SENTINEL masters1)1)name2)mymaster3)ip4)redis-master5)port6)63797)flags8)master9)num-slaves10)2...127.0.0.1:26379SENTINEL slaves mymaster1)1)name2)172.18.0.3:63793)ip4)172.18.0.3...127.0.0.1:26379SENTINEL sentinels mymaster(列出所有监控 mymaster 的哨兵)看到这些信息说明 3 个哨兵已经成功发现主节点和从节点系统处于健康监控状态。5. 模拟故障转移亲眼见证自动切换5.1 停止主节点等待约 5~10 秒down-after-milliseconds为 5000ms观察哨兵日志dockerlogs sentinel1--tail20关键日志行sdown master mymaster redis-master6379odown master mymaster redis-master6379#quorum 2/2try-failover master mymaster redis-master6379vote-for-leader... elected-leader master mymaster redis-master6379failover-state-select-slave master mymaster redis-master6379selected-slave slave172.18.0.3:6379... redis-slave16379failover-state-send-slaveof-noone slave redis-slave1:6379 failover-state-wait-promotion slave redis-slave1:6379 promoted-slave slave redis-slave1:6379 failover-state-reconf-slaves master mymaster... slave-reconf-sent slave redis-slave2:6379 failover-end master mymaster redis-master6379switch-master mymaster redis-master6379172.18.0.36379日志清晰地展示了完整过程检测主观下线 → 达成客观下线共识 → 选举哨兵领导 → 选择最佳从节点 → 提升为新主 → 重配置其他从节点。5.2 验证新主节点# 查看新主状态dockerexecredis-slave1 redis-cli INFO replication|greprole# role:master# 查看原从节点 2 是否指向新主dockerexecredis-slave2 redis-cli INFO replication|grepmaster_host# master_host:172.18.0.3 (即 redis-slave1)原主节点恢复后会自动变成从节点dockerstart redis-master# 几秒后dockerexecredis-master redis-cli INFO replication|greprole# role:slave6. Python 客户端对接 Sentinel最关键的环节来了应用如何自动感知主节点切换答案是使用 Sentinel 感知的客户端。6.1 安装 redis-py6.2 Sentinel 连接方式redis-py提供了Sentinel类来管理主从发现from redis.sentinelimportSentinelimporttime# 配置所有哨兵地址sentinel_hosts[(localhost,26379),(localhost,26380),(localhost,26381),]# 创建 Sentinel 客户端sentinelSentinel(sentinel_hosts,socket_timeout0.5)# 从哨兵获取当前主节点和从节点mastersentinel.master_for(mymaster,socket_timeout0.5,decode_responsesTrue)slavesentinel.slave_for(mymaster,socket_timeout0.5,decode_responsesTrue)# 写操作走主节点master.set(username,IT策士)master.set(counter,100)print(f写入完成: username{master.get(username)}, counter{master.get(counter)})# 读操作走从节点print(f从节点读取: username{slave.get(username)}, counter{slave.get(counter)})# 获取当前主节点的实际地址master_addrsentinel.discover_master(mymaster)print(f当前主节点地址: {master_addr})slavessentinel.discover_slaves(mymaster)print(f当前从节点列表: {slaves})输出示例写入完成:usernameIT策士,counter100从节点读取:usernameIT策士,counter100当前主节点地址:(172.18.0.3,6379)当前从节点列表:[(172.18.0.4,6379),(172.18.0.2,6379)]6.3 验证故障转移对客户端透明编写一个持续读写的脚本来测试from redis.sentinelimportSentinelimporttimesentinelSentinel([(localhost,26379),(localhost,26380),(localhost,26381),],socket_timeout0.5)mastersentinel.master_for(mymaster,socket_timeout0.5,decode_responsesTrue,retry_on_timeoutTrue)print(开始持续写入...)foriinrange(1000): try: keyfkey:{i % 10}valuefvalue:{i}master.set(key, value)resultmaster.get(key)print(f[{i:03d}] SET/GET {key} {result})time.sleep(0.1)except Exception as e: print(f[{i:03d}] 错误: {e})time.sleep(0.5)# 等待故障转移完成print(测试结束)在脚本运行期间用docker stop redis-slave1停掉当前主节点观察输出[042]SET/GET key:2value:42[043]SET/GET key:3value:43[044]SET/GET key:4value:44[045]错误: Connection refused[046]错误: Connection refused[047]SET/GET key:7value:47 ← 恢复自动连上新主[048]SET/GET key:8value:48客户端在短暂报错后自动恢复无需任何人工干预。这就是 Sentinel 的核心价值。6.4 封装高可用客户端类from redis.sentinelimportSentinel from typingimportList, Tuple class RedisHA:Sentinel 高可用 Redis 客户端 def __init__(self, sentinel_hosts: List[Tuple[str, int]], service_name: strmymaster, socket_timeout: float0.5, decode_responses: boolTrue): self.sentinelSentinel(sentinel_hosts,socket_timeoutsocket_timeout)self.service_nameservice_name self.decode_responsesdecode_responses self._masterNone self._slaveNone property def master(self):获取主节点连接自动发现returnself.sentinel.master_for(self.service_name,socket_timeout0.5,decode_responsesself.decode_responses,retry_on_timeoutTrue)property def slave(self):获取从节点连接轮询returnself.sentinel.slave_for(self.service_name,socket_timeout0.5,decode_responsesself.decode_responses,retry_on_timeoutTrue)def get_master_addr(self):获取当前主节点地址returnself.sentinel.discover_master(self.service_name)def get_slaves(self):获取所有从节点returnself.sentinel.discover_slaves(self.service_name)def set(self, key, value, **kwargs):returnself.master.set(key, value, **kwargs)def get(self, key):returnself.slave.get(key)def delete(self, key):returnself.master.delete(key)# 使用cacheRedisHA(sentinel_hosts[(localhost,26379),(localhost,26380),(localhost,26381)])cache.set(app:version,3.0)print(cache.get(app:version))print(f当前主节点: {cache.get_master_addr()})7. 生产环境最佳实践哨兵数量至少 3 个且部署在不同物理机或可用区。偶数个哨兵会增加投票平局的概率。quorum 设置sentinel_num / 2 1例如 3 哨兵设 25 哨兵设 3。客户端超时和重试设置socket_timeout和retry_on_timeout避免因网络抖动抛异常。监控哨兵本身哨兵也可能挂需要监控哨兵进程的存活和SENTINEL masters的正确性。避免在故障转移期间操作故障转移一般 10~30 秒此期间短暂不可写入是正常现象。不要将哨兵和数据节点混布在同一台机器否则机器宕机时数据节点和哨兵一起挂。8. 动手试试模拟主节点宕机在 Python 持续写入时docker stop主节点观察恢复时间。模拟哨兵宕机停掉 1 个哨兵观察剩下 2 个是否仍能正常完成故障转移quorum2。查看故障转移后配置检查哨兵配置文件看sentinel monitor行是否自动更新为新主地址。网络分区模拟通过 Docker 网络隔离主节点观察哨兵的行为和客户端恢复。预期效果主节点宕机后 10~20 秒自动恢复写入单哨兵宕机不影响集群可用性配置文件自动更新网络分区恢复后旧主变为从。9. 总结Sentinel 让 Redis 从“单点可用”跃升为“真正的自动高可用”。但它无法解决写的横向扩展——所有写入仍然只能走一个主节点。下一篇我们将迎来 Redis 的终极形态Redis Cluster用哈希槽实现数据分片彻底突破单机瓶颈。想了解更多还可以去各个平台搜索「IT策士」一起升级 IT 思维
Redis 从入门到精通:Redis Sentinel 哨兵
发布时间:2026/6/13 21:39:07
IT策士 10余年一线大厂经验专注 IT 思维、架构、职场进阶。我会在各个平台持续发布最新文章助你少走弯路。上一篇我们搭建了 Redis 主从架构实现了数据冗余和读写分离。但有个致命问题当主节点宕机时必须手动将某个从节点提升为主节点再通知其他从节点和所有应用修改连接地址。这个过程少则几分钟多则半小时对于核心业务来说完全不可接受。Redis Sentinel哨兵就是为解决这个问题而生的。它能自动监控主从节点、自动发现故障、自动完成故障转移让 Redis 真正具备生产级高可用能力。本文带你从原理到实战用 Docker 搭建完整哨兵集群并用 Python 客户端对接感受自动故障转移的丝滑体验。1. Sentinel 是什么解决了什么问题Sentinel 是一套独立的分布式监控系统它由多个哨兵进程组成共同协作完成三个核心任务监控Monitoring持续检查主节点和从节点是否正常运行。通知Notification当节点状态发生变化时通过 API 或脚本通知管理员和其他应用。自动故障转移Automatic Failover当主节点不可用时自动选举一个从节点升级为新主节点并让其他从节点和新主节点同步。架构图┌──────────────┬──────────────┬──────────────┐ │ Sentinel1│ Sentinel2│ Sentinel3│ ← 哨兵集群至少3个 └──────┬───────┴──────┬───────┴──────┬───────┘ │ │ │ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Master │───│ Slave1│ │ Slave2│ └──────────┘ └──────────┘ └──────────┘ Sentinel 本身不存储数据它是独立于 Redis 数据节点的控制平面。即使没有 SentinelRedis 也能正常工作加上 Sentinel就拥有了自动化的“守护神”。2. 核心原理主观下线与客观下线哨兵判断一个节点是否故障用了两层机制。2.1 主观下线SDOWN每个哨兵进程每隔 1 秒向主节点、从节点、其他哨兵发送PING命令。如果某个节点在down-after-milliseconds配置项默认 30 秒时间内没有有效回复这个哨兵自身就会标记该节点为主观下线Subjectively Down。但单个哨兵的判断可能失误——比如自己的网络出了故障。所以不能仅凭 SDOWN 就发起故障转移。2.2 客观下线ODOWN当某个哨兵发现主节点进入 SDOWN 后它会询问其他哨兵“你们也觉得主节点挂了吗” 当达到quorum法定人数通常为哨兵数量的半数以上个哨兵都认为主节点下线该节点就被标记为客观下线Objectively Down。此时哨兵集群会通过Raft 算法选举出一个哨兵领导者由它来执行故障转移。2.3 故障转移流程哨兵领导者从所有健康的从节点中按优先级、复制偏移量、runid 等规则选出最合适的一个。向被选中的从节点发送SLAVEOF NO ONE将其提升为主节点。向其他从节点发送SLAVEOF 新主IP 新主端口让它们同步新主。将旧主节点的地址更新到哨兵配置中一旦旧主恢复它将成为新主的从节点。整个过程通常在10~30 秒内完成。⚠️ Sentinel 只对主节点做客观下线判断。从节点和哨兵节点只需要主观下线即可做出反应。3. 关键配置参数详解在开始实战之前先理解 Sentinel 的核心配置项# sentinel.conf 核心配置# 监控的主节点名称、IP、端口、quorum法定人数sentinel monitor mymaster127.0.0.163792# 主观下线判定超时毫秒超过此时间无响应则 SDOWNsentinel down-after-milliseconds mymaster5000# 故障转移最大超时毫秒超过此时间未完成则重新选举领导者sentinel failover-timeout mymaster10000# 新主节点同步时允许同时同步的从节点数量越小同步越慢但主节点压力小sentinel parallel-syncs mymaster1# 哨兵端口port26379quorum 建议3 个哨兵设quorum25 个哨兵设quorum3。这保证即使少数哨兵故障也能正常完成故障转移。4. 实战Docker 搭建 Sentinel 集群我们搭建一个“1 主 2 从 3 哨兵”的完整环境。4.1 整体架构Sentinel 集群26379/26380/26381 │ ▼ 主节点 Master6379 │ ┌───┴───┐ ▼ ▼ Slave16380 Slave263814.2 创建网络和主从节点# 创建网络dockernetwork create sentinel-net# 启动主节点dockerrun-d--nameredis-master--networksentinel-net\-p6379:6379 redis:7.2 redis-server--appendonlyyes# 启动从节点 1dockerrun-d--nameredis-slave1--networksentinel-net\-p6380:6379 redis:7.2 redis-server\--appendonlyyes--slaveofredis-master6379# 启动从节点 2dockerrun-d--nameredis-slave2--networksentinel-net\-p6381:6379 redis:7.2 redis-server\--appendonlyyes--slaveofredis-master6379验证主从状态dockerexecredis-master redis-cli INFO replication|grepconnected_slaves# connected_slaves:24.3 配置并启动 3 个哨兵首先在宿主机创建哨兵配置文件3 份# 创建目录mkdir-p~/sentinel/conf# 哨兵配置文件cat~/sentinel/conf/sentinel.confEOF port 26379 dir /data sentinel monitor mymaster redis-master 6379 2 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 10000 sentinel parallel-syncs mymaster 1 EOF# 复制为 3 份端口不同cp~/sentinel/conf/sentinel.conf ~/sentinel/conf/sentinel1.confcp~/sentinel/conf/sentinel.conf ~/sentinel/conf/sentinel2.confcp~/sentinel/conf/sentinel.conf ~/sentinel/conf/sentinel3.conf⚠️ 实际生产中 3 个哨兵最好部署在不同物理机上这里仅演示原理都放在同一台机器。启动哨兵容器# 哨兵 1 (端口 26379)dockerrun-d--namesentinel1--networksentinel-net\-p26379:26379\-v~/sentinel/conf/sentinel1.conf:/etc/redis/sentinel.conf\redis:7.2 redis-sentinel /etc/redis/sentinel.conf# 哨兵 2 (端口 26380)dockerrun-d--namesentinel2--networksentinel-net\-p26380:26379\-v~/sentinel/conf/sentinel2.conf:/etc/redis/sentinel.conf\redis:7.2 redis-sentinel /etc/redis/sentinel.conf# 哨兵 3 (端口 26381)dockerrun-d--namesentinel3--networksentinel-net\-p26381:26379\-v~/sentinel/conf/sentinel3.conf:/etc/redis/sentinel.conf\redis:7.2 redis-sentinel /etc/redis/sentinel.conf4.4 验证哨兵状态连接到任意哨兵查看信息dockerexec-itsentinel1 redis-cli-p26379127.0.0.1:26379SENTINEL masters1)1)name2)mymaster3)ip4)redis-master5)port6)63797)flags8)master9)num-slaves10)2...127.0.0.1:26379SENTINEL slaves mymaster1)1)name2)172.18.0.3:63793)ip4)172.18.0.3...127.0.0.1:26379SENTINEL sentinels mymaster(列出所有监控 mymaster 的哨兵)看到这些信息说明 3 个哨兵已经成功发现主节点和从节点系统处于健康监控状态。5. 模拟故障转移亲眼见证自动切换5.1 停止主节点等待约 5~10 秒down-after-milliseconds为 5000ms观察哨兵日志dockerlogs sentinel1--tail20关键日志行sdown master mymaster redis-master6379odown master mymaster redis-master6379#quorum 2/2try-failover master mymaster redis-master6379vote-for-leader... elected-leader master mymaster redis-master6379failover-state-select-slave master mymaster redis-master6379selected-slave slave172.18.0.3:6379... redis-slave16379failover-state-send-slaveof-noone slave redis-slave1:6379 failover-state-wait-promotion slave redis-slave1:6379 promoted-slave slave redis-slave1:6379 failover-state-reconf-slaves master mymaster... slave-reconf-sent slave redis-slave2:6379 failover-end master mymaster redis-master6379switch-master mymaster redis-master6379172.18.0.36379日志清晰地展示了完整过程检测主观下线 → 达成客观下线共识 → 选举哨兵领导 → 选择最佳从节点 → 提升为新主 → 重配置其他从节点。5.2 验证新主节点# 查看新主状态dockerexecredis-slave1 redis-cli INFO replication|greprole# role:master# 查看原从节点 2 是否指向新主dockerexecredis-slave2 redis-cli INFO replication|grepmaster_host# master_host:172.18.0.3 (即 redis-slave1)原主节点恢复后会自动变成从节点dockerstart redis-master# 几秒后dockerexecredis-master redis-cli INFO replication|greprole# role:slave6. Python 客户端对接 Sentinel最关键的环节来了应用如何自动感知主节点切换答案是使用 Sentinel 感知的客户端。6.1 安装 redis-py6.2 Sentinel 连接方式redis-py提供了Sentinel类来管理主从发现from redis.sentinelimportSentinelimporttime# 配置所有哨兵地址sentinel_hosts[(localhost,26379),(localhost,26380),(localhost,26381),]# 创建 Sentinel 客户端sentinelSentinel(sentinel_hosts,socket_timeout0.5)# 从哨兵获取当前主节点和从节点mastersentinel.master_for(mymaster,socket_timeout0.5,decode_responsesTrue)slavesentinel.slave_for(mymaster,socket_timeout0.5,decode_responsesTrue)# 写操作走主节点master.set(username,IT策士)master.set(counter,100)print(f写入完成: username{master.get(username)}, counter{master.get(counter)})# 读操作走从节点print(f从节点读取: username{slave.get(username)}, counter{slave.get(counter)})# 获取当前主节点的实际地址master_addrsentinel.discover_master(mymaster)print(f当前主节点地址: {master_addr})slavessentinel.discover_slaves(mymaster)print(f当前从节点列表: {slaves})输出示例写入完成:usernameIT策士,counter100从节点读取:usernameIT策士,counter100当前主节点地址:(172.18.0.3,6379)当前从节点列表:[(172.18.0.4,6379),(172.18.0.2,6379)]6.3 验证故障转移对客户端透明编写一个持续读写的脚本来测试from redis.sentinelimportSentinelimporttimesentinelSentinel([(localhost,26379),(localhost,26380),(localhost,26381),],socket_timeout0.5)mastersentinel.master_for(mymaster,socket_timeout0.5,decode_responsesTrue,retry_on_timeoutTrue)print(开始持续写入...)foriinrange(1000): try: keyfkey:{i % 10}valuefvalue:{i}master.set(key, value)resultmaster.get(key)print(f[{i:03d}] SET/GET {key} {result})time.sleep(0.1)except Exception as e: print(f[{i:03d}] 错误: {e})time.sleep(0.5)# 等待故障转移完成print(测试结束)在脚本运行期间用docker stop redis-slave1停掉当前主节点观察输出[042]SET/GET key:2value:42[043]SET/GET key:3value:43[044]SET/GET key:4value:44[045]错误: Connection refused[046]错误: Connection refused[047]SET/GET key:7value:47 ← 恢复自动连上新主[048]SET/GET key:8value:48客户端在短暂报错后自动恢复无需任何人工干预。这就是 Sentinel 的核心价值。6.4 封装高可用客户端类from redis.sentinelimportSentinel from typingimportList, Tuple class RedisHA:Sentinel 高可用 Redis 客户端 def __init__(self, sentinel_hosts: List[Tuple[str, int]], service_name: strmymaster, socket_timeout: float0.5, decode_responses: boolTrue): self.sentinelSentinel(sentinel_hosts,socket_timeoutsocket_timeout)self.service_nameservice_name self.decode_responsesdecode_responses self._masterNone self._slaveNone property def master(self):获取主节点连接自动发现returnself.sentinel.master_for(self.service_name,socket_timeout0.5,decode_responsesself.decode_responses,retry_on_timeoutTrue)property def slave(self):获取从节点连接轮询returnself.sentinel.slave_for(self.service_name,socket_timeout0.5,decode_responsesself.decode_responses,retry_on_timeoutTrue)def get_master_addr(self):获取当前主节点地址returnself.sentinel.discover_master(self.service_name)def get_slaves(self):获取所有从节点returnself.sentinel.discover_slaves(self.service_name)def set(self, key, value, **kwargs):returnself.master.set(key, value, **kwargs)def get(self, key):returnself.slave.get(key)def delete(self, key):returnself.master.delete(key)# 使用cacheRedisHA(sentinel_hosts[(localhost,26379),(localhost,26380),(localhost,26381)])cache.set(app:version,3.0)print(cache.get(app:version))print(f当前主节点: {cache.get_master_addr()})7. 生产环境最佳实践哨兵数量至少 3 个且部署在不同物理机或可用区。偶数个哨兵会增加投票平局的概率。quorum 设置sentinel_num / 2 1例如 3 哨兵设 25 哨兵设 3。客户端超时和重试设置socket_timeout和retry_on_timeout避免因网络抖动抛异常。监控哨兵本身哨兵也可能挂需要监控哨兵进程的存活和SENTINEL masters的正确性。避免在故障转移期间操作故障转移一般 10~30 秒此期间短暂不可写入是正常现象。不要将哨兵和数据节点混布在同一台机器否则机器宕机时数据节点和哨兵一起挂。8. 动手试试模拟主节点宕机在 Python 持续写入时docker stop主节点观察恢复时间。模拟哨兵宕机停掉 1 个哨兵观察剩下 2 个是否仍能正常完成故障转移quorum2。查看故障转移后配置检查哨兵配置文件看sentinel monitor行是否自动更新为新主地址。网络分区模拟通过 Docker 网络隔离主节点观察哨兵的行为和客户端恢复。预期效果主节点宕机后 10~20 秒自动恢复写入单哨兵宕机不影响集群可用性配置文件自动更新网络分区恢复后旧主变为从。9. 总结Sentinel 让 Redis 从“单点可用”跃升为“真正的自动高可用”。但它无法解决写的横向扩展——所有写入仍然只能走一个主节点。下一篇我们将迎来 Redis 的终极形态Redis Cluster用哈希槽实现数据分片彻底突破单机瓶颈。想了解更多还可以去各个平台搜索「IT策士」一起升级 IT 思维