Redis高可用实战:主从复制、哨兵与Cluster架构全解析 聊一个面试里经常被问、生产环境里也特别现实的问题怎么实现Redis的高可用先说结论Redis高可用不是靠某一个功能搞定的而是一套组合方案。核心就三件事——数据有冗余、故障能发现、流量能切换。很多刚接触Redis的同学容易把持久化当成高可用或者以为主从复制就是高可用实际上它们解决的是完全不同的问题。这篇文章我会从架构演进的顺序把主从复制、哨兵、Cluster三套方案的设计思路、工作原理、实操配置和常见坑一次讲透。无论你是要把单机Redis升级成高可用架构还是在面试中需要把这个问题答出深度这篇文章都应该对你有用。1. 高可用到底在解决什么问题先想清楚再动手1.1 单机Redis为什么撑不住我在生产环境里见过不少业务一开始就是用一台Redis支撑的。最典型的状态就是服务器上跑着一个redis-server进程代码里把连接池地址指向这一台机器读写全都压在这一个进程上。刚开始业务量不大一切都很正常。等流量上来、数据量涨上去问题就开始集中爆发。第一是单点故障。机器宕机、Redis进程被系统杀掉、磁盘损坏、机房断电随便哪一项都会让整个业务直接断掉。没有备用节点出问题只能等这台机器恢复恢复时间完全不可控很多时候要按小时来算。对于线上服务来说这就是不可用事故。第二是容量瓶颈。一台机器的内存是有限的Redis作为一个内存型数据库数据总量直接受制于单机内存。业务缓存数据一旦增长到上百GB单机的内存成本会很高而且内存满了之后还需要处理淘汰策略或者直接拒绝写入。第三是并发压力。虽然Redis是单线程模型处理请求极快但高性能不代表无限扩展。当热点key的访问量达到每秒几十万甚至上百万次时单机网卡、CPU中断处理都会成为瓶颈被打穿是早晚的事。所以高可用架构的第一个目标就是把“这台机器挂了”从致命故障降级成可恢复的小问题。要做到这一点必须要有冗余。简单说就是多准备几台机器彼此之间把数据同步好一台出了问题另一台能顶上。1.2 高可用不等于数据持久化这是一个我反复拿来说的误区。很多人把RDB和AOF持久化开好就觉得Redis已经高可用了。实际上持久化解决的是进程重启后数据不丢的问题或者说进程崩溃后能从磁盘恢复数据。但它完全不处理“这台机器彻底废了”的情况。举个例子你开好了AOF每秒钟fsync一次。某个夜里机器硬件故障磁盘直接读不出来Redis进程彻底起不来了。这时候持久化的文件还在磁盘上可机器已经没法用了你在其它服务器上没有第二份数据业务还是只能干等直到把你备份出来的RDB文件拷贝到新机器上重新加载。所以说清楚一点持久化保障的是“进程只能崩溃数据尽量不丢”高可用保障的是“单点故障之后服务还能继续以可用状态运行”。一个管数据安全一个管服务连续。这两件事都要做但不能互相替代。正确的顺序应该是先把持久化开好再在这个基础上叠加冗余和自动切换。1.3 高可用的本质冗余加自动切换高可用系统的核心逻辑用一句话概括就是多副本冗余加上故障自动切换。冗余负责让数据在多个节点上存在自动切换负责在某个节点不可用时让客户端把请求打到还在正常工作的节点上。生活里这个逻辑很常见。比如手机有两张SIM卡一张信号掉了手动切到另一张。手动切换的问题是什么你得先发现信号掉了再找到设置界面再切换整个过程慢而且容易出错。如果这张卡恰好是备用卡但人正在外地切换成本会很高。所以真正高可用的系统核心其实在“自动”这两个字上。Redis生态里解决自动切换的组件就是后面重点讲的哨兵Sentinel和Cluster自带的主从切换机制。从单机到主从复制再到哨兵再到Cluster本质上是分工越来越明确一个组件承担一个专业任务。理解了这条演进路线你会发现自己对Redis高可用的理解会变得特别通透。2. 第一层方案主从复制正确但不够2.1 主从复制能带来什么主从复制英文叫Replication是Redis高可用体系里的第一层地基。思路很简单指定一个节点为主节点master其他节点作为从节点replica主节点处理写入请求然后把写入的数据同步到从节点上。我用一个实际场景来说明价值。某电商团队的订单缓存原先部署在单机Redis上后来他们把架构改成一主两从主节点负责读写两个从节点一个用来做数据备份、一个给数据分析部门做临时查询。改造之后最大的感受是单台机器起了争议只要主节点不挂业务照常跑。即使主节点真的出问题至少数据在从节点上还留着一份不至于从零开始恢复。如果从更细的角度看主从复制至少带来三个价值第一个是数据冗余从节点持有一份和主节点几乎一致的数据这是后面所有高可用方案的基础第二个是读写分离可以把读流量分摊到多个从节点上降低主节点的压力第三个是备份方案可以更灵活比如在从节点上执行BGSAVE不会影响主节点的性能。2.2 复制流程从全量到增量主从复制的底层流程很多同学只知道一个大概真要你说清楚却讲不明白。这里值得认真梳理一遍。当一个从节点首次连接主节点时从节点会发送PSYNC命令要求同步数据。如果主节点发现这是第一次同步或者从节点已经落后太多就会执行一次全量同步full resync。全量同步的过程是主节点在后台执行BGSAVE生成一份RDB快照同时把生成快照期间收到的所有写命令缓存到复制积压缓冲区repl_backlog_buffer里RDB生成完毕后主节点把RDB文件发给从节点从节点清空旧数据并加载RDB随后主节点再把缓冲区里积压的写命令发给从节点从节点逐条执行最终两边数据保持一致。全量同步完成后正常运行时走的是增量同步。主节点每执行一条写命令都会把命令传播给各个从节点从节点接一条执行一条主从之间始终保持接近一致。另外从节点还会定期向主节点发送心跳确认网络连接还活着。这里有一个很关键的点Redis 4.0之前如果主从之间网络短暂中断从节点重连后通常需要全量同步一次代价非常大。Redis 4.0之后主从都保存了复制偏移量offset和运行IDreplid只要断线时间不长、offset还在复制积压缓冲区的范围内就能通过部分重同步partial resync补上中间丢失的命令成本比全量同步小得多。这也是为什么我会建议有条件就把Redis版本升到4.0以上生产环境里能少很多麻烦。2.3 主从模式下的故障处理主从复制虽然做到了数据有冗余但它的故障处理能力非常弱。这一点必须提前说清楚免得部署完以为是高可用了结果出了问题还是抓瞎。在主从架构里如果从节点挂了影响其实是可控的。主节点照常工作只是少了一个备份和读节点。等从节点恢复后重新连上主节点双方会自动做增量同步数据会慢慢追平。但如果主节点挂了麻烦就来了。所有写请求都会直接失败因为只有主节点才能处理写入。从节点虽然有一份数据但它不会自动提升为新的主节点。这时候需要运维人员或者某个脚本登录到从节点上手动执行REPLICAOF NO ONE命令让它变成主节点然后通知所有业务方把连接地址改成这台新的主节点。整个过程完全依赖人去发现、去判断、去操作。如果是半夜两三点主节点宕机等人接到告警、爬起来、操作完业务已经不可用很长时间了RTO恢复目标几乎不可控。我见过不止一个团队以为上了主从复制就高枕无忧了结果主节点一挂大家手忙脚乱地找从节点、改配置、切流量最后业务恢复了复盘时发现恢复时间竟然花了几十分钟。这就是主从复制最大的短板有冗余但没有自动切换。要解决这个问题就需要引入哨兵。2.4 主从架构里的几个常见坑在主从架构里有一些细节问题特别容易被忽略我这里挑几个印象深刻的。第一是配置不一致。从节点默认是只读的如果你把从节点配置成可写很可能出现数据不一致的问题。生产环境里请务必将replica-read-only保持开启不要改。第二是身份认证。如果你在主节点设置了requirepass开启了密码认证那么从节点同步时需要配置masterauth从节点的Redis实例也需要设置requirepass否则会出现同步失败但主节点日志里看半天看不出原因的情况。第三是复制积压缓冲区的大小。repl-backlog-size这个参数直接决定了部分重同步能容忍多大的断线时间。默认值是1MB对于写比较频繁的业务来说实在太少了。一般建议根据峰值写命令大小和允许的断线时间相乘来估算。比如每秒写入量约5MB希望容忍30秒断线缓冲区至少得150MB左右否则一旦网络抖动就会触发全量同步性能开销不小。3. 第二层方案哨兵把“自动”做出来3.1 哨兵解决的核心痛点主从复制解决了数据冗余剩下的最大痛点就是故障切换要靠人。哨兵Sentinel就是为了把这一步变成自动的而出现的。哨兵本质上是一个独立的Redis服务但它做的事情不是存数据而是监控。它盯着的目标是数据节点主节点master和从节点replica。当它发现主节点不可用时会执行一个故障转移failover流程从当前健康的从节点里挑一个提升为新的主节点并通知其他从节点和新主节点建立复制关系同时把变化告诉客户端。整个过程中业务方不需要人工介入RTO可以压缩到秒级。我在实际项目里见过一个很典型的案例。某公司的一套会员积分系统Redis从一主一从升级到一主两从加三哨兵之后后来遇到过一次底层物理机出现问题主节点在没有任何征兆的情况下失联。哨兵大概在十几秒内完成了探测和切换业务方只是感觉到有少量请求超时并没有造成大面积故障。这跟之前主从复制那套手动恢复流程相比体验完全不是一个等级。3.2 哨兵怎么判断一个节点挂了哨兵判断节点挂了分成两个阶段主观下线和客观下线。哨兵会周期性向所有节点发送心跳命令PING如果被监控的节点在指定时间内没有正常回复这个哨兵就会认为该节点可能已经挂了。注意这里用的是“可能”因为可能是网络抖动、可能是哨兵自己所在机器的问题。在单个哨兵的视角里它只能得到一个“主观下线”sdownsubjectively down的判断。如果有多个哨兵情况就不一样了。当一个哨兵认为主节点主观下线时它会把这个判断通过发布订阅通道和节点间通信广播给其他哨兵。其他哨兵收到消息后也去检查自己到主节点的连通性。当判断主节点主观下线的哨兵数量达到我们配置的quorum数值时主节点就会被判定为“客观下线”odownobjectively down这才触发了后面真正的故障转移流程。这里有个重要的认知点哨兵本身也必须部署成集群而且通常建议至少三个哨兵实例。因为如果只有一个哨兵哨兵自己也成了单点同时它一个人说了算碰到网络分区可能误判。三个哨兵配合quorum机制可以让判断更可靠。一般实践是部署三个哨兵quorum设为2这样任何一个哨兵说挂了还不够还得有另一个哨兵确认误判概率大大降低。3.3 故障转移到底是怎么执行的一旦主节点被判定为客观下线哨兵集群接下来要做的事是选举出故障转移的执行者。不是每个哨兵都能执行切换需要先选出一个leader。这个选举机制和Raft有一些相似的地方每个哨兵都可以发起投票请求收到多数派同意后成为leader然后由leader具体负责故障转移。leader哨兵执行切换时会做这么几件事首先从目前存活的从节点列表里筛选出优先级最高的候选者。这里会综合考量多个因素——从节点的复制偏移量越新越好越接近主节点数据、丢的数据越少越好然后看从节点的优先级配置slave-priority数值越小优先级越高最后还要看从节点所在机器是否和已下线主节点在同一物理机或机架上如果在一起可能一起被端掉通常优先级会更低。选择好新的主节点后leader会向这个从节点发送REPLICAOF NO ONE命令让它取消对原主节点的复制关系切换成新的主节点。然后leader会向其他从节点发送REPLICAOF 新主节点IP 新主节点端口命令让它们同步新的主节点。如果原主节点后面恢复了哨兵也会让它降级为新主节点的从节点重新加入复制拓扑保证整个架构最终回到一个健康状态。整个故障转移过程中客户端如何自动感知新主节点呢两条路。一种是通过哨兵提供的API主动获取当前主节点信息可以通过SENTINEL get-master-addr-by-name命令查询另一种是订阅哨兵的频道当发生主从切换时哨兵会向switch-master频道发布消息客户端收到消息后再更新连接地址。市面上的主流客户端都在这个机制上做了封装。3.4 哨兵部署的实操建议实操层面哨兵配置文件里最关键的几项带大家过一遍。sentinel monitor mymaster 127.0.0.1 6379 2 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 15000 sentinel parallel-syncs mymaster 1第一行里的2就是quorum值表示需要两个哨兵判定主节点主观下线才能触发客观下线同时故障转移领导者选举也需要多数的哨兵参与。注意quorum设为多少最好结合哨兵总数来定不是越大越好。哨兵总数是3的时候quorum设为2比较合理。如果哨兵总数是5quorum可以设成3。down-after-milliseconds表示哨兵和主节点失联多久后认为它不存活。默认值一般调低一些但也不能太低否则轻微的GC停顿、网络抖动就会触发误判。我实际使用中一般设5秒到10秒之间具体取决于业务对抖动容忍度。failover-timeout是故障转移超时时间这个值设置过小会导致切换过程中各种步骤失败后没有足够时间重试设置过大又会让客户端等待时间过长。通常从10秒到60秒之间都有人用建议结合网络环境逐步调优。parallel-syncs表示新主节点就位后同时允许多少个从节点发起全量同步。如果从节点很多全量同步会占用大量带宽和IO。建议设为1让从节点一个一个地同步虽然总体切换时间会长一点但风险更可控。另外部署哨兵的时候不要把所有哨兵塞在同一台物理机上否则这台机器一挂三个哨兵全没了分布式判断也就失去了意义。更合理的方式是三台哨兵部署在不同的机器或者不同的可用区让它们的故障域尽量隔离。4. 第三层方案Cluster从高可用走向高扩展4.1 哨兵架构解决不了容量问题哨兵架构在主从复制的基础上实现了自动切换解决了单点故障问题。但如果你只用哨兵还是会遇到一个天花板容量问题。我参与维护过一套使用哨兵架构的Redis高峰期数据量涨到几百GB单台主节点的内存已经逼近物理上限。无论你怎么加从节点数据的总量还是只有一份副本从节点只是复制品几乎没有扩展能力。写并发也是类似所有写请求都集中在主节点上主节点的CPU和网络带宽最终会成为瓶颈。这时候需要的是分片也就是把数据分散存储到多个主节点上每个主节点只负责一部分数据整体能力可以随着主节点数量的增加而扩展。Redis Cluster就是在这个思路上诞生的方案。它把高可用和水平扩展整合到一个系统里不再需要外部哨兵单独管理。这也是为什么现在越来越多新的生产环境选择直接上Cluster。4.2 数据如何分片16384个槽Cluster分片的单位是哈希槽hash slot整个集群一共有16384个槽位。集群初始化或者扩容时会把这些槽位分配到各个主节点上。写入一个key的时候客户端或者集群内部会对key做CRC16运算再对16384取模得到一个槽号然后根据槽位和节点的对应关系确定该key应该被路由到哪个节点。举个例子某个key经过计算落到第5000号槽如果主节点A负责3000到6000号槽那么这个key就会被保存在节点A上。读取的时候同理先计算槽号再访问对应节点。这里有一个很关键的细节槽位的分配是自动管理还是手动管理取决于你用什么工具。官方推荐的redis-cli --cluster create命令会自动把16384个槽平均分配到所有主节点上而如果你手动创建集群就必须手工把每个槽指派给某个节点。不管用哪种方式槽的分配信息都会被所有节点共享客户端也知道该去访问谁。在Cluster中每个主节点都可以配置一个或多个从节点。主节点负责一部分槽的读写流量从节点作为这些槽的备份。如果某个主节点挂了它的从节点会自动提升为主节点接管这些槽继续提供服务。所以Cluster里的主从复制组是分片维度的每个分片都有自己的高可用能力整体的可用性由所有分片共同保证。4.3 Cluster的故障转移和复制组Cluster的故障转移和哨兵有相似之处也有明显区别。相同点是都需要通过心跳检测节点状态。Cluster中的每个节点会定期和其他节点交换状态信息包括Gossip协议传播消息。当一个主节点在规定时间内没有被绝大多数节点确认存活它就会被集群标记为疑似下线随后其他节点也会异步确认最终判定为真正下线。区别在于Cluster没有单独的哨兵集群角色而是由各个Redis节点自己协作完成判断和切换。当一个主节点被判定为下线后它的从节点会尝试发起选举。从节点会向集群中其他主节点请求投票如果获得了大多数主节点的同意它就会提升自己为新的主节点并接管原来主节点负责的槽位。之后集群会广播新主节点的信息客户端重新获取槽位映射关系继续提供服务。从高可用角度看Cluster本身就是一整套完整方案。配置集群时只需要在所有节点上把cluster-enabled设为yes再指定cluster-config-file保存槽位状态的配置文件然后通过集群管理工具把节点组建起来。不需要额外启动哨兵进程整体架构更简洁减少了运维摆弄的组件。4.4 Cluster部署中常见的坑虽然Cluster功能强大但部署过程中有不少需要注意的地方踩过的坑我给大家列一列。第一是端口规划。每个Redis Cluster节点会使用两个TCP端口一个是具体的客户端端口比如6379另一个是集群总线端口默认是客户端端口加10000比如16379专门用于节点间通信。如果你在云上部署要确保这两组端口在网络策略里同时放通。很多人只放通了6379结果节点之间互相联系不上集群创建失败或者反复尝试错误。第二是客户端的兼容性。使用Cluster模式时你的客户端必须支持Cluster协议才能正确处理节点返回的MOVED错误和ASK错误完成路由跳转。老版本客户端或者一些简单的连接池工具并不支持这些使用之前一定要确认。选型时可以考虑官方推荐的一些主流客户端它们对Cluster的支持比较完善。第三是批量操作的约束。因为key会被分布到不同槽位所以像MSET、MGET这种跨多个key的命令如果key不在同一个槽位上会直接报错。解决办法是使用Hash Tag比如把相关key的命名设计成{user1001}.name、{user1001}.age这样Redis只会对花括号内的部分计算槽位同一组key会被映射到同一个槽位。第四是PUBSUB和Lua脚本的问题。PUBSUB事件在Cluster模式下默认是广播到所有节点的这在订阅量和节点数比较大的时候会带来额外的网络开销。一些Lua脚本如果涉及到多个key这些key必须都在同一个槽位上否则脚本执行会失败。设计和编码阶段就要把这一点考虑进去。第五是maxmemory的设置。在Cluster模式里如果每个节点单独设置maxmemory由于不同节点的数据量并不均匀可能出现某个节点率先内存溢出的情况。建议确保所有节点的内存配置一致同时定期关注热点槽位带来的数据倾斜。5. 三种方案怎么选架构选型要算清楚5.1 几个方案的能力对比把三种架构拉到一个表格里对比结论会非常直观。维度单机主从复制哨兵Cluster数据冗余无有有有自动故障切换无无有有水平扩展不支持不支持不支持支持数据分片无无无16384个槽组件复杂度低低中中高适用数据量GB级以内单机内存内单机内存内可扩展到TB级典型RTO小时级分钟级需人工秒级到十几秒秒级到十几秒从这张表能很清楚地看出主从复制是基础哨兵在主从基础上加了自动化Cluster又在哨兵基础上加了水平扩展能力。它们之间不是互相取代的关系而是层级递进的关系。5.2 按业务场景选型的建议选型不能只看技术指标还得结合实际业务情况。如果你的业务数据量小比如缓存总量在几十GB以内并且可以接受主节点宕机后人工介入恢复那么主从复制是最简单的选择。很多内部管理系统、低峰期明显的中小型业务都够用。但前提是团队里有人能被叫起来处理问题而且RTO可以容忍到分钟级别。如果业务已经在线上了要求主节点出问题后服务能自动恢复比如电商平台、金融交易系统那么至少得上哨兵架构。部署成本不算高三台哨兵加一主两从即可。我建议大部分中小团队优先从这个方案开始把高可用的自动切换做起来再考虑后续的容量扩展。如果业务的数据量增长空间非常大或者已经出现单机内存不够用、写并发打满的情况那就需要认真评估Cluster了。Cluster的优点是既有自动故障转移又有分片扩展缺点是需要客户端支持、运维复杂度上升、批量操作和脚本有约束。如果团队没有足够的Redis运维经验可以先在测试环境充分演练不要贸然全量切换。另外还要考虑一个混合架构的思路。比如核心的热点数据放在哨兵架构里追求最低延迟冷数据或者大数据量的分析场景放到Cluster里。这个策略在一些团队里效果不错但会增加使用成本日常维护时要对两套系统有充足的监控。6. 高可用落地后的常见故障与排查实录6.1 主从切换后丢数据我自己处理过不少切换后丢数据的案例要说清楚还得从复制机制讲起。Redis主从复制默认是异步的主节点处理完写命令后立刻返回客户端之后再异步把命令传播给从节点。这就意味着如果主节点在某个写命令还没有传播给从节点的时候突然宕机哨兵或Cluster提升新主节点时这条命令就永远丢了。业务侧看到的现象就是切换后一部分最新写入的数据不见了。缓解办法是让主从之间的数据差距尽量小。一是尽量确保网络质量主从之间不要跨地域部署二是合理配置min-replicas-to-write和min-replicas-max-lag这个机制可以限制主节点在从节点跟不上时仍然接受写入。比如可以配置当从节点延迟超过10秒后主节点就不再接受写入虽然这会牺牲一定的可用性但能显著降低大量数据丢失的概率。具体配多少要看业务对数据丢失的容忍程度靠极端的一方都不可取。6.2 脑裂最危险的一种故障脑裂是分布式系统里最棘手的问题之一Redis高可用架构里也会遇到。场景是主节点和哨兵之间网络出了问题哨兵判定主节点客观下线自动把某个从节点提升为新的主节点。但原来的主节点其实还活着只是暂时联系不上哨兵和从节点。网络恢复后原主节点发现自己已经降级但在这段时间内原主节点可能仍然在接收客户端的写入请求因为有些客户端保持老连接写入原主节点。这就导致原主节点和新的主节点各写各的数据分成两半。等原主节点重新加入集群并降级为从节点时它会试图从新主节点同步数据结果是它自己那段时间新增的数据被清空。业务方看到的表象就是一部分用户数据回滚或者丢失。解决脑裂核心靠两点首先是确保客户端始终通过哨兵获取当前主节点的地址而不是把IP写死在连接配置里这样主节点变更后客户端才会跟着切走其次就是要配置上面提到的min-replicas-to-write和min-replicas-max-lag让原主节点在失联期间也尽量拒绝对外的写入。我遇到过某个团队上线几年一直平稳运行觉得这两个参数无所谓后来一次机房网络抖动就吃了大亏代价很大。6.3 哨兵迟迟不切换或反复切换哨兵不切换最常见的原因就是quorum配置不合理或者哨兵节点之间的通信被防火墙挡住。如果你发现主节点明明挂了哨兵却没有执行故障转移优先检查三件事哨兵之间是否能互通哨兵是否能连接主从节点quorum值是否配置正确。如果哨兵进程日志里出现了大量down和恢复交替的信息多半是网络抖动加上down-after-milliseconds设置过短导致的可以把阈值适度调大。反复切换的另一个常见原因是各从节点的数据落后程度相差很大选主时哨兵挑了一个数据不够新的从节点之后客户端一写入又发现问题导致频繁切换。这时候最好检查一下主节点和从节点之间的复制延迟延迟过大的从节点建议配置更低的选举优先级或者先暂停它的同步任务等数据追平再放回集群。6.4 主从延迟与复制断裂即使高可用架构搭好了主从复制延迟仍然是一个容易踩的坑。如果业务对数据一致性要求比较严格比如库存、余额等数据直接读从节点很可能会读到旧值。主从延迟变高常见原因有几个。第一个是大key操作比如一次性写入一个几MB甚至几十MB的字符串或者一个超大的列表从节点同步时同样要处理这个大数据量耗时自然拉长。解决方案是尽量拆分大key避免单次写入过大。第二个是网络带宽主从之间如果跨机房同步延迟和带宽限制会放大波动。第三个是从节点执行其他耗时操作比如同时开启了比较重的AOF rewrite导致同步命令队列堆积。复制断裂之前我们提到过只要断线时间控制在合理范围内部分重同步就能接上。但如果发现整个从节点每次都触发全量重同步一定要检查repl-backlog-size是不是太小了以及网络断线时间是否经常超出缓冲区的容忍范围。把积压缓冲区调大效果往往立竿见影。6.5 Cluster迁移卡住与访问异常Cluster在reshard也就是槽迁移过程中偶尔也会出现一些诡异的问题。最典型的场景是迁移过程中包含一些特别大的key单个key的迁移时间很长在此期间这个槽位处于迁移状态客户端访问可能收到ASK错误需要重定向到目标节点。如果客户端没有正确处理ASK重定向就可能出现请求失败。遇到迁移卡住或者卡很久的情况先别急着杀掉迁移进程先看目标节点和源节点的网络和磁盘IO尤其是磁盘IO是否被打满。另外要注意迁移期间不要同时做非常重的AOF重写尽量把维护操作错开减少对节点性能的影响。访问异常还有一个容易被忽略的点就是集群的配置文件cluster-config-file如果没有持久化保存好节点重启后可能丢失槽位信息导致整个集群的元数据混乱。生产环境里要把这个文件和RDB/AOF一样纳入备份体系节点恢复后能快速找回正确的槽位分布。最后说说我的体会前面这几套方案我都亲身维护过踩过不少坑也积累了一些经验。最大的体会是高可用不是部署完就结束的它是一个需要持续演练和验证的状态。很多团队上线了哨兵或者Cluster之后就再也没动过直到某天真的出了问题才发现配置里有个参数从一开始就设错了或者客户端接入方式本身就写得不支持自动切换。我个人非常推荐定期做故障演练比如选个业务低峰期手动把主节点进程杀掉或者直接切断网络观察哨兵能否完成切换、客户端能否自动恢复、数据延迟在什么范围。这个动作看起来简单但能暴露的问题非常多远比读十篇文档有帮助。另外一定要关注可观测性。高可用系统自身的监控指标非常关键比如主从复制延迟、哨兵节点的状态、Cluster的槽位分布、节点之间的网络质量。这些指标应该被采集出来并设置告警而不是等业务方反馈问题之后才去看日志。最后再分享一个小细节配置高可用方案时一定不要忘记从节点的持久化配置。有些团队觉得从节点只是备份不用开AOF和RDB结果主节点数据损坏需要从节点顶上的时候才发现从节点重启后是空的人为制造了一次严重事故。从节点也给足持久化配置地基建稳Redis这套高可用地基才能真正撑得住大流量。