Redis集群和哨兵一起用,保证服务不停歇,高可用真不是说说而已
- 问答
- 2025-12-29 13:13:29
- 3
(引用来源:主要基于Redis官方文档关于高可用性的架构讨论,以及业界常见的生产环境部署最佳实践)

Redis要想真正做到服务不停歇,光靠一种技术是不够的,这就好比你要保护一座重要的城堡,不能只修一道城墙,还得有巡逻的卫兵和备用的城堡,Redis集群和哨兵(Sentinel)一起用,就是构建了这样一套立体的防御体系。
我们得明白它们各自是干什么的,Redis集群的核心任务是分片,也就是把海量的数据分散到多个Redis节点上存储,比如你有1个T的数据,一个Redis实例可能扛不住,但你可以把它分成5份,每份200G,交给5个不同的Redis实例(我们称之为主节点)来存,这样,每个节点压力就小多了,实现了数据量的横向扩展,Redis集群自身也带有高可用功能:每个主节点都可以配备一个或多个从节点(副本),主节点负责写,从节点实时同步主节点的数据,一旦主节点宕机了,集群内部能自己协商,并从它的从节点中选举出一个新的主节点来顶替,继续提供服务,这听起来已经很好了,对吧?但这里有个关键问题:这个选举和故障切换的过程,是由Redis集群自己来管理的,但它并不负责把这个“换主了”的消息及时、可靠地通知给外部的客户端。

这时候,哨兵的作用就凸显出来了,你可以把哨兵系统想象成一组非常忠诚且时刻保持警惕的“哨兵”,它们不存储任何业务数据,唯一的任务就是不停地监控所有的Redis主节点和从节点是否健康,哨兵通常是奇数个(比如3个或5个)一起部署,它们之间会互相通信,形成一个“哨兵集群”,这样可以防止单个哨兵自己出问题导致误判。
当某个主节点被哨兵们判定为“主观下线”(即一个哨兵觉得它挂了)后,其他哨兵会去确认,如果达到一定数量的哨兵都认为它挂了,就会判定为“客观下线”,哨兵们会自动发起一次投票,从已下线主节点的从节点中选出一个新的主节点,哨兵会执行两个至关重要的操作:第一,通知剩下的从节点,让它们去复制新的主节点;第二,也是最核心的一步,哨兵会更新一个全局的“服务发现”信息,告诉所有客户端:“喂,之前那个主节点换了,现在新的主节点是这个地址!”
我们把两者结合起来看,为什么“一起用”能实现更高的可用性,在这种架构下,我们通常会让Redis集群专注于做它最擅长的事情——数据分片和集群内部的故障转移,而哨兵集群则作为一个更高层次的、独立的“监控和治理中心”,它的职责是:
- 更可靠的监控:哨兵专注于监控,它的监控逻辑和故障检测机制比Redis集群内置的要更细致、更健壮,它可以从多个角度判断一个节点是否真的不可用,减少了误判的可能。
- 统一的客户端接入点:对于客户端来说,它不需要知道Redis集群内部有多少个分片,每个分片的主节点地址是什么,客户端只需要连接到哨兵系统,询问:“我要访问的Redis服务,当前的主节点在哪里?”哨兵就会返回正确的地址,这样,即使某个分片发生了主从切换,客户端通过再次询问哨兵,就能无感知地连接到新的主节点,实现了真正的“服务不停歇”。
- 管理便利性:哨兵提供了一个中心化的视图,运维人员可以通过哨兵轻松地查看整个Redis集群的健康状态,甚至可以在必要时通过哨兵手动进行主从切换,进行维护操作。
举个例子来串一下整个流程:假设我们有一个3分片的Redis集群,每个分片是1主2从,我们部署了3个哨兵进程。
- 正常运行时:客户端App向哨兵询问写地址,哨兵返回3个主节点的地址,App愉快地读写数据。
- 发生故障:分片2的主节点突然宕机。
- 集群动作:Redis集群检测到分片2的主节点失联,于是在分片2的两个从节点中自动选举出新的主节点。但此时,客户端App并不知道这个变化。
- 哨兵动作:哨兵几乎同时监控到分片2原主节点下线,经过确认和投票后,哨兵认可了集群内部选举出的新主节点,哨兵立即更新自己的服务发现信息。
- 客户端恢复:当客户端App再次尝试向已经宕机的原主节点写入时,会发现连接失败,这时,设计良好的客户端库会有一个“重试”逻辑,它会主动回头再去问哨兵:“分片2现在的主节点是谁?”哨兵给出新主节点的地址,客户端重新建立连接,继续写入,整个过程对应用程序来说,可能只是一次短暂延迟或自动重试,服务没有中断。
Redis集群解决了数据量大和节点故障内部切换的问题,而哨兵解决了故障切换后客户端无感知自动切换的问题,两者相辅相成,共同构成了一道坚固的防线,确保了Redis服务的高可用性,这确实不是纸上谈兵,而是经过大量线上环境验证的、切实可行的方案,部署和维护这套架构会比单机Redis复杂,但为了业务的高可用和数据的可靠性,这种投入是值得的。

本文由歧云亭于2025-12-29发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://www.haoid.cn/wenda/70669.html
