ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Redis哨兵高可用集群搭建:一主两从三哨兵与故障转移实战

2026/9/18 9:08:51 拓冰建站 浏览量
Redis哨兵高可用集群搭建:一主两从三哨兵与故障转移实战 1. 为什么单机 Redis 迟早会出事先把场景摆出来。你手上有个项目Redis 装在一台机器上跑得好好的某天凌晨三点告警响了Redis 进程挂了或者那台机器磁盘满了、内存被打爆触发 OOM Killer、机房网络抖了一下。结果就是所有依赖 Redis 的业务全线报错缓存击穿直接怼到数据库上数据库跟着一起倒。这个链条我在真实环境里见过不止一次恢复顺序永远是先把 Redis 拉起来再慢慢重启下游服务。问题不在于 Redis 本身不稳而在于单点。一台机器承载了所有读写它没有冗余没有接管者挂了就是挂了。哨兵模式Sentinel存在的唯一理由就是解决这件事让一组独立的进程盯着你的 Redis 实例主节点不行了就自动选一个新的顶上去客户端重新连到新主节点上继续干活。说得再直白一点哨兵干三件事。第一是监控它持续对主从节点发心跳判断谁活着谁死了。第二是通知某个节点出问题时它能通过事件机制告诉外界。第三是自动故障转移主节点被判定客观下线后哨兵集群内部先选出一个 Leader由这个 Leader 从剩下的从节点里挑一个提升为新主节点然后把其余从节点指向新主节点最后通知客户端。你需要几个概念先垫底不然后面配置看不懂。哨兵自己也是一个 Redis 进程只不过启动时用的是redis-sentinel或者redis-server xxx.conf --sentinel它不存业务数据只存配置和状态。哨兵之间也互相通信通过发布订阅同一个频道来交换对主节点的判断。还有个关键阈值叫法定人数quorum指的是至少多少个哨兵认为主节点挂了才能进入客观下线流程这个数直接决定故障判断的灵敏度。谁该看这篇两种情况。一种是你正在准备面试redis面试题里哨兵和集群的区别、故障转移流程、脑裂怎么处理这些是高频考点光背结论没用得自己搭一遍才有画面感。另一种是你负责的服务还跑在单机 Redis 上想升级成高可用架构但不知道从哪下手。这篇就按“从零搭一套能跑的三节点哨兵”的路径走顺带把每个参数为什么这么设讲清楚。2. 搭之前必须定下来的几件事动手之前先别急着敲命令有几个决策点定错了后面全是返工。我把踩过的坑按顺序列一下。2.1 节点数量与拓扑怎么选哨兵集群的节点数必须是奇数。原因不复杂哨兵选 Leader 用的是类似 Raft 的多数派投票机制需要超过半数同意。3 个节点能容忍 1 个挂掉5 个节点能容忍 2 个挂掉。2 个节点是最糟的配置因为一旦有一个挂了剩下一个凑不够多数派整个故障转移能力直接瘫痪还不如单机。生产环境的常见组合是3 个 Redis 数据节点1 主 2 从 3 个哨兵进程。数据节点和哨兵可以混部但我强烈建议不要把哨兵和它监控的主节点放在同一台机器上。道理很简单机器整体宕机的时候主节点和同机的哨兵一起没了剩下的哨兵虽然还能投票但数量可能刚好卡在临界点。所以理想情况是 3 台机器每台跑一个 Redis 实例加一个哨兵主从关系跨机器。我见过有人图省事3 个哨兵全塞一台机器上只把 Redis 实例分开。这种配置在机器宕机时同样会丢掉多数哨兵等于白搭。哨兵的高可用价值有一半来自它自身的地理分散这点一定要想明白。2.2 主从复制是哨兵的前置条件哨兵不负责复制数据它只负责切换。数据的一致性靠的是主从复制也就是从节点持续从主节点同步数据。所以顺序是先搭好一主多从确认复制正常再上哨兵。如果主从都没通哨兵切过去也只是把客户端指向一个空数据的从节点业务照样炸。验证主从是否正常最简单的办法是在主节点上SET一个 key然后去从节点GET能取到就说明复制通了。或者用INFO replication看从节点的master_link_status是不是up。2.3 环境与版本准备Redis 版本建议用 6.2 及以上的稳定版哨兵在这个版本区间已经非常成熟。如果你追求新特性Redis 8 也完全可以用哨兵的行为模型没有大变化。安装方式上Linux 生产环境我推荐源码编译或者包管理器安装Windows 只适合本地学习因为 Windows 版的 Redis 官方早已不再积极维护。环境推荐安装方式适用场景Linux生产源码编译 / apt / yum正式部署Linux测试Docker 容器快速复现Windows学习第三方编译版 / WSL本地练手如果用docker安装redis主从这套路子练手注意容器网络的坑哨兵配置里写IP:PORT容器之间必须能通过这个 IP 互相访问。用 Docker Compose 起一个自定义网络让容器用服务名互访比直接映射宿主机端口再写宿主机 IP 要干净得多。还有一点容易被忽略时间同步。三台机器的系统时间如果差得多日志时间戳会错乱排查故障时非常折磨人。装个 NTP 同步一下几分钟的事。3. 从零开始一主两从加三哨兵实操这一节是核心我按真实操作顺序走一遍。假设你有三台机器IP 分别是 10.0.0.11、10.0.0.12、10.0.0.13规划如下。机器Redis 角色端口哨兵端口10.0.0.11主节点63792637910.0.0.12从节点63792637910.0.0.13从节点6379263793.1 redis 安装配置主从节点配置差异先在三台机器上都装好 Redis。源码编译的话流程大概是下载、解压、make、make install产物在src/目录下。用包管理器更省事apt install redis-server或者yum install redis都行。接下来改配置。主节点10.0.0.11的redis.conf关键几项bind 0.0.0.0 port 6379 daemonize yes dir /var/lib/redis logfile /var/log/redis/redis.log appendonly yes requirepass YourStrongPassword masterauth YourStrongPassword这里有两个点要说明。bind 0.0.0.0是为了让其他机器能连进来生产环境强烈建议配合防火墙规则限制来源 IP。requirepass和masterauth要设成一样的密码前者是客户端连本实例要用的密码后者是从节点连主节点时用的密码。如果只设requirepass不设masterauth从节点会因为认证失败连不上主节点复制一直起不来——这个坑我踩过日志里会刷NOAUTH Authentication required。从节点10.0.0.12和10.0.0.13的配置在主节点基础上多一行replicaof 10.0.0.11 6379注意从节点默认是只读的replica-read-only yes这是对的别去改。有人为了能让从节点写数据把只读关了结果主从数据直接冲突得不偿失。配完启动三台 Redis然后在主节点上执行INFO replication应该看到role:master和connected_slaves:2。在从节点上执行同样的命令应该看到role:slave和master_link_status:up。看到这个主从就通了。3.2 哨兵配置文件逐行拆解哨兵用独立的配置文件一般叫sentinel.conf。三台机器内容基本一致只有个别地方不同。先看内容port 26379 daemonize yes dir /var/lib/redis logfile /var/log/redis/sentinel.log sentinel monitor mymaster 10.0.0.11 6379 2 sentinel auth-pass mymaster YourStrongPassword sentinel down-after-milliseconds mymaster 30000 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000 sentinel deny-scripts-reconfig yes protected-mode no逐行说清楚这些都是面试和实战都会问的。sentinel monitor mymaster 10.0.0.11 6379 2这行是灵魂。mymaster是你给这套主从起的名字客户端连接哨兵时要指定这个名字所以三台哨兵必须一致。后面的 IP 和端口是初始主节点注意只需要写初始主节点哨兵自己会发现从节点不需要你手动列出来。最后的2就是 quorum意思是至少 2 个哨兵认为主节点挂了才判定客观下线。sentinel auth-pass mymaster YourStrongPassword是主节点的密码因为哨兵要连上去发INFO和PING。这个如果不设而主节点有密码哨兵会一直连不上日志里能看到认证错误。sentinel down-after-milliseconds mymaster 30000是主观下线的时间阈值单位毫秒。意思是哨兵发PING后30 秒内没收到有效回复就认为这个节点主观下线。这个值设太小会误判网络抖一下就把主切了设太大故障恢复慢。30 秒是个比较稳的起点。sentinel parallel-syncs mymaster 1控制故障转移后同时向新主节点发起同步的从节点数量。设成 1 意味着一个一个来降低新主节点被同步请求瞬间压垮的风险。从节点多的时候这个值很关键。sentinel failover-timeout mymaster 180000是故障转移的超时时间单位毫秒180 秒。这个参数的含义比较绕它同时管好几件事两次针对同一主节点的故障转移之间的最小间隔、故障转移的最大允许时间等。默认 180 秒一般够用除非你的数据量特别大全量同步特别慢。注意sentinel monitor里的 quorum 和“故障转移需要的多数派”是两个概念很多人会混。quorum 是判定客观下线的票数而真正执行故障转移时Leader 选举需要的是超过半数哨兵的投票跟 quorum 不一定相等。3.3 启动哨兵并验证集群状态配置文件写好后启动命令是redis-sentinel /etc/redis/sentinel.conf或者redis-server /etc/redis/sentinel.conf --sentinel两种等价。启动后连上任意一个哨兵执行redis-cli -p 26379 sentinel master mymaster会输出一大堆信息重点看几个字段。num-other-sentinels应该是 2说明它发现了另外两个哨兵。flags里如果带master说明当前它认为这个节点是主。num-slaves应该是 2。如果num-other-sentinels是 0多半是哨兵之间没通检查防火墙和protected-mode配置。再执行sentinel sentinels mymaster能看到另外两个哨兵的详细信息。执行sentinel slaves mymaster能看到两个从节点的信息。这三个命令是日常排障的基本盘记住。有个细节值得注意哨兵启动后会重写自己的配置文件。你原来写的sentinel monitor mymaster 10.0.0.11 6379 2在发生故障转移后这行会被自动改成新的主节点 IP 和端口。所以不要惊讶配置文件自己变了这是正常行为也是哨兵持久化状态的方式。同理从节点信息也会被追加进去。这就带来一个实操要点改哨兵配置一定要在哨兵停止的时候改运行中改容易被它自己重写覆盖掉。3.4 模拟主节点故障与观察切换过程搭完不验证等于没搭。验证故障转移最直接的办法就是把主节点进程杀掉看哨兵是否自动切换。操作如下redis-cli -h 10.0.0.11 -p 6379 -a YourStrongPassword shutdown nosaveshutdown nosave不保存 RDB 直接退出模拟突然宕机。然后立刻在另一个终端连上哨兵执行redis-cli -p 26379 sentinel master mymaster盯着flags和ip字段看。大约 30 秒你设的 down-after-milliseconds后哨兵会判定主观下线再过一小会儿进入客观下线然后开始选举 Leader、挑选新主节点。整个过程通常在 30 到 40 秒之间完成。切换完成后ip字段会变成某个从节点的 IPflags仍然是master。同时去看哨兵的日志/var/log/redis/sentinel.log里面会有一串清晰的阶段记录类似sdown主观下线、odown客观下线、vote-for-leader投票、switch-master切换完成。这套日志是排查故障转移问题最有价值的材料建议花时间读一遍。切换完成后还有两件事要确认。一是原来那个从节点有没有被重新配置为指向新主节点用sentinel slaves mymaster看。二是新主节点上INFO replication是不是显示role:master且从节点数正确。3.5 客户端怎么接哨兵这一点经常被忽略但它是整个方案落地的最后一公里。客户端不能直连主节点 IP那样主节点一换客户端就懵了。正确做法是连接哨兵集群由哨兵返回当前主节点地址。以 Java 的 Jedis 为例配置大概是SetString sentinels new HashSet(); sentinels.add(10.0.0.11:26379); sentinels.add(10.0.0.12:26379); sentinels.add(10.0.0.13:26379); JedisSentinelPool pool new JedisSentinelPool(mymaster, sentinels, YourStrongPassword);注意mymaster这个名字必须和哨兵配置里的一致。Spring Boot 项目里用spring.redis.sentinel.master和spring.redis.sentinel.nodes两个配置项。这里有个高频面试点客户端连接池在故障转移期间会怎么样。答案是会抛异常因为切换期间主节点地址短暂不可用连接池需要重建。所以业务代码一定要有重试机制或者用 Lettuce 这类支持自动重连的客户端。还有一点哨兵节点要全列上不要只写一个。客户端会轮询哨兵列表只写一个的话那个哨兵挂了就麻烦了。4. 参数背后的账算清楚再设很多教程给完配置就结束了但参数设错导致的故障比配置错误更隐蔽。这一节把几个关键参数的来龙去脉算一遍。4.1 故障判定时间到底怎么来的一次完整故障转移的耗时大致等于下面几段之和主观下线判定down-after-milliseconds我设的是 30000 毫秒客观下线达成哨兵之间交换信息通常几百毫秒到几秒Leader 选举几轮网络往返一般 1 秒内挑选新主节点并执行提升取决于从节点状态通常 1 到 5 秒其他从节点切换复制源取决于parallel-syncs和数据量所以 30 秒阈值下端到端恢复一般在 35 到 45 秒。如果你的业务对故障恢复时间有要求比如要求 10 秒内恢复那down-after-milliseconds得往下调比如 5000。但代价是网络抖动更容易触发误判。这个参数本质上是灵敏度和平稳性的权衡没有标准答案得根据你的网络质量和对停机时间的容忍度来定。我个人的经验是内网环境质量好设 10000 到 15000 是比较好的平衡点。跨机房或者云环境网络波动大老老实实设 30000。4.2 parallel-syncs 为什么建议设小故障转移后新主节点需要和所有从节点建立复制关系从节点会发起全量或部分同步。如果parallel-syncs设成从节点总数那么切换瞬间所有从节点同时向新主节点要数据新主节点既要处理业务又要吐 RDB压力陡增。设成 1一次只让一个从节点同步其余排队。代价是全部从节点完成同步的时间变长。假设一个从节点全量同步要 20 秒两个从节点串行就是 40 秒。这段时间内还没同步完的从节点数据是滞后的如果新主节点又挂了这个滞后的从节点被选为新主就会丢数据。所以从节点数量多、单次全量同步慢的场景需要在parallel-syncs和同步时长之间找平衡。4.3 脑裂最容易被问倒的坑脑裂split-brain指的是网络分区导致出现两个主节点两边都在接受写请求等网络恢复后一边的数据会被丢弃。哨兵模式下脑裂是怎么发生的比如主节点和所有哨兵之间的网络断了主节点自己还在正常运行并接受客户端写入而哨兵这边认为主节点挂了选了新主节点这就出现了两个主。Redis 提供了两个参数来缓解min-replicas-to-write 1 min-replicas-max-lag 10含义是主节点必须至少有 1 个从节点且从节点的延迟不超过 10 秒否则主节点拒绝写入。这样当主节点被网络隔离、连不上从节点时它会主动停止接受写入等分区恢复后也就不会有新旧主节点的数据冲突。代价是可用性下降从节点全挂的时候主节点也写不了了。这是个取舍业务对数据一致性要求高就开对可用性要求高就慎重。面试里被问到哨兵模式怎么防脑裂把这两个参数报出来再解释清楚它牺牲的是什么基本就答满了。5. 常见问题与排查技巧实录搭的过程和用的过程一定会出问题这一节按我遇到的频率排一下都配上排查路径。5.1 哨兵之间互相发现不了现象是sentinel master mymaster里num-other-sentinels一直是 0。先检查三台哨兵的sentinel monitor行是不是完全一致名字、IP、端口、quorum 四要素有一个不同就发现不了对方因为哨兵是通过向__sentinel__:hello频道发布消息来互相发现的订阅的是同一个主节点。再检查防火墙有没有放开 26379 端口以及protected-mode是不是设成了no。另外如果哨兵所在的 Redis 实例设了密码而哨兵没有requirepass注意哨兵自身的密码和它监控的主节点密码是两回事也可能影响。5.2 主节点密码导致的认证失败日志里刷NOAUTH或者ERR Client sent AUTH, but no password is set。前者是哨兵没配sentinel auth-pass后者是哨兵配了密码但主节点没设。还有一种情况是masterauth没配从节点连不上主节点。这三个密码配置要成对检查。5.3 故障转移后客户端连不上切换完了但业务报连接错误。八成是客户端还在用旧的主节点地址或者客户端没有重试逻辑。检查客户端的哨兵配置是不是列全了哨兵节点以及用的是不是哨兵连接模式而不是单机模式。如果你用的是redis desktop manager或者another redis desktop manager这类可视化工具看数据注意它们大多只支持直连单个实例不支持哨兵自动发现。这时你得手动连当前主节点主节点一换就得重新连。用redis insight的话对哨兵支持好一些。这点在排查时要有心理准备别以为是集群坏了。5.4 故障转移反复触发主节点恢复后又被切来回折腾。多半是down-after-milliseconds设太小加上网络不稳。也可能是failover-timeout设得太短导致第一次转移还没完全结束就触发了下一次。把这两个值适当调大先观察日志确认触发原因。5.5 数据丢失问题哨兵本身不保证零丢失。因为 Redis 主从复制是异步的主节点收到写请求后返回成功但数据可能还没同步到从节点这时主节点挂了切换后这段数据就没了。想减少丢失可以考虑WAIT命令做同步复制确认或者用min-replicas-to-write限制写入条件。但真正的强一致要靠 Redis Cluster 的多数派写入或者其他方案哨兵在这件事上能力有限别抱不切实际的期望。下面这张表汇总一下常见现象和对症下药的方向。现象可能原因排查方向哨兵发现不了彼此配置不一致、防火墙、protected-mode检查 monitor 行、端口、网络认证失败密码配置缺失或不一致检查 requirepass / masterauth / auth-pass切换后客户端连不上客户端未用哨兵模式或未重试检查客户端配置和重试逻辑反复切换判定阈值过小调大 down-after 和 failover-timeout切换后丢数据异步复制固有缺陷用 WAIT 或 min-replicas 缓解5.6 几个实测下来很稳的操作习惯第一哨兵配置改完用redis-sentinel自带的检查方式验证一遍再重启别嫌麻烦。第二保留哨兵日志至少留 7 天故障复盘时它比任何监控面板都详细。第三定期演练手动杀掉主节点验证切换别等到真出事才发现切换不好使。第四给主从节点的监控加上master_link_status和复制延迟两个指标它们能在故障发生前给你预警。第五如果项目用的是 Spring Bootredis在springboot中的使用里关于哨兵模式的配置坑不少特别是连接池参数和超时时间记得单独压测一遍。这套东西搭下来从零到能跑大概两三个小时调试的时间主要花在网络和密码这两个坎上。我个人在实际操作中的体会是哨兵这套机制的设计其实不复杂真正的难度在于把每个参数和它对应的故障场景对应起来你要能看着一个参数说出它在什么情况下起作用、设大了设小了分别会出什么问题。能做到这一点不管是面试还是线上排障都不会慌。