2026/10/11 9:14:23

Redis主从复制实战:从原理到高可用架构的完整指南

Redis主从复制实战:从原理到高可用架构的完整指南 开着电脑准备部署测试环境的那天我其实低估了Redis主从复制的坑。当时的思路很简单一台Redis实例跑得好好的为什么要搞一主两从直到半夜线上Redis因为服务器重启直接宕机缓存雪崩打进数据库那一个小时我整个人是懵的。后来把主从复制真正吃透才意识到这东西不只是“多存几份数据”那么简单。它背后牵涉数据高可用、读流量负载均衡、故障转移、一致性取舍还有一堆配置文件里看似不起眼却能让你失眠的参数。这篇文章不讲虚的纯粹以我自己的实操路径为主线把Redis主从复制的原理、搭建方式、客户端接入、故障处理到如何升级成哨兵和集群一条一条掰开揉碎。如果你是要接手公司Redis运维的后端或者准备自己搭一套带冗余的缓存体系又或者面试时被人问“主从复制到底复制了什么”那这篇文章你应该能直接抄作业。无论你现在用的是单机版还是已经在Docker里跑过redis-server都不影响阅读。1. 主从复制到底在解决什么问题1.1 单机Redis的七个软肋我先说个扎心的事实默认配置下单机Redis就是一个看起来很快、实际很脆的组件。快是因为数据在内存里脆是因为它把所有鸡蛋放在了一个篮子中。第一个问题就是单点故障。Redis进程挂了或者所在机器重启、磁盘损坏、网络被切断整个缓存层就没了。更麻烦的是如果没有好的持久化配置Redis重启后可能会变成空库这时候所有请求会穿透到数据库数据库大概率扛不住。第二个问题是读流量。很多人误以为Redis单机性能无上限其实内存操作再快CPU、网卡、内存带宽也都是有标尺的。当业务请求量涨上来一个线程处理串行指令是有瓶颈的尤其在高并发情况下只读操作甚至会拖垮主进程的响应。比如你们做秒杀用户都在刷商品详情每次刷新都是一堆GET一两万个QPS就能把单实例压得喘不过气。第三个问题是备份困难。虽然RDB和AOF都可以做持久化但如果在高负载实例上执行BGSAVEfork子进程会带来短暂的内存和CPU波动如果直接在业务实例上做备份打扰主进程是必然的。你总不能在用户最活跃的时候跑一把重备份吧。除此之外还有版本升级、配置调整、故障演练等场景单机架构下全都要停服。这些问题不是Redis本身的缺陷而是分布式系统里单点架构必然面对的限制。主从复制解决的就是这些软肋中的一部分数据冗余、读扩展、备份不打扰。1.2 复制不等于高可用这点必须分清日常生活中大家经常把“复制”和“高可用”混着说实际是两码事。复制把主节点的数据实时同步到从节点让从节点多一份完整副本。这意味着主节点磁盘坏了还有从节点的数据在读流量也可以分流到从节点上。但复制本身不会自动帮你在主节点挂掉时切换角色。也就是说当master宕机replica上虽然有一份最新数据但客户端还是连接在master的IP和端口上业务照样不可用。你需要手动登录到redis命令行执行REPLICAOF NO ONE把某个从节点提升为主节点再修改所有客户端的连接地址或者依赖额外的哨兵组件去自动完成这个动作。所以“主从复制”是高可用的地基但不是高可用本身。这句话我在面试别人时几乎必问答不上来的人往往是把复制和故障转移当成了一件事。1.3 别指望从节点帮你挡FLUSHALL还有一点经常被忽略主从复制做的是“命令流同步”不是“隔离容灾”。你在主节点上执行FLUSHALL这条命令同样会原封不动地同步到从节点。我曾经在一次演练中不小心在生产主库上把某张前缀的缓存清掉了结果所有从库在同一秒钟也全清空了。如果当时指望“主库误操作了但从库还有旧数据”来兜底那就是白日梦。由此也引出一个重要结论主从复制主要防的是硬件故障、进程崩溃、网络分区这类基础设施层面的问题防不了逻辑错误和误操作。真正的误删保护需要额外的备份体系比如定时把从库RDB文件拷贝到对象存储并保留周期版本才能做到。所以在设计高可用方案时千万别把复制和备份混为一谈。2. 深入拆解复制原理全量同步、增量同步与断线续传2.1 一次完整全量同步发生的全过程当你第一次把一个节点配置成某个主节点的从节点时或者从节点和主节点断开太久导致部分同步条件不满足时就会发生全量同步。全量同步到底做了什么我按顺序拆给你看。从节点启动时会向主节点发送PSYNC命令带上一个特殊的参数表示“我没有历史数据希望你给我全量数据”。主节点收到这个请求后立即把当前状态记录下来主要包含两部分一份是当前的replid复制ID用来标识数据流版本另一个是当前最新的复制偏移量master_repl_offset。接下来主节点开始处理快照生成。它先执行一次类似于BGSAVE的流程把内存里的数据打包成RDB文件。注意这一步是fork一个子进程去做的主进程不会被阻塞还能继续接受写请求。但这会带来一个时间窗口RDB生成期间产生的所有写操作怎么办主节点会把它们统统记录到内存里的复制积压缓冲区repl_backlog里。RDB文件生成完成后主节点把这个文件通过连接发给从节点。从节点收到后先清空自己的旧数据再加载RDB文件把状态恢复到快照时刻。紧接着主节点把复制积压缓冲区里新缓存的写命令再流式发送过来从节点一条条执行掉。等到双方处理完这些增量数据主节点的master_repl_offset和从节点的slave_repl_offset对齐全量同步才算真正完成。这里有个很多人问我的点RDB文件到底是走磁盘还是走网络Redis有两种路径。默认情况下主节点把RDB先写到磁盘再读盘发送给从节点这叫disk-backed如果开启repl-diskless-sync yes则生成RDB时直接通过socket流式传输给从节点不落盘。磁盘类型对IO压力更敏感但兼容性更好diskless在网卡带宽充足、磁盘性能差时更合适尤其当你有多个从节点需要同时全量同步时diskless能明显减轻磁盘压力。2.2 PSYNC 与断线续传为什么主从不会一断就连全量Redis 2.8之前每次断线重连都要全量同步代价极高后来引入了PSYNC协议支持部分重同步。这个机制的关键是复制积压缓冲区和一个偏移量。从节点在线时会跟主节点保持一个offset表示自己已经消费到了数据流的哪个位置。如果从节点短暂断开它在断开的这段时间里主节点依旧接收写请求产生新的数据放进写命令序列同时也会积累到复制积压缓冲区里。当从节点重新连接时会发送PSYNC replid offset主节点一看哦你要的这份数据我还保存在缓冲区里那就继续从offset开始把剩下的增量命令发给你不需要重新生成RDB耗时和带宽都大幅下降。但如果从节点离线太久或者主节点的复制积压缓冲区配得太小导致offset对应的数据已经被新数据覆盖这时主节点就没办法做部分同步了只能退回到全量同步。你可以把repl_backlog理解成一个环形队列容量有限旧数据会被新数据顶掉。所以生产环境里千万不要用默认值建议根据从节点可能的离线时长来配置repl-backlog-size。我自己的习惯是如果业务高峰写可达每秒20MB希望容忍从节点离线60秒后重连仍能增量续传那repl-backlog-size至少需要20MB * 60秒 1200MB。当然这只是一个理论下限实际服务器内存足够的话我会直接给到512MB到1GB。内存占用虽然多了一点但换来的是尽可能避免全量重同步对带宽和主节点fork压力来说是划算的。2.3 复制过程中的细节过期key、只读从库与多级级联过期key在主从复制里的处理方式容易让新手困惑。从库默认不会主动去清过期key也不会自行删除过期数据它只是傻等主库的命令。当主库端发现某个key过期了它会执行一条DEL然后这个DEL会同步到从库执行。这样做的根本原因是为了保证主从数据一致性避免主从各自删key造成状态分叉。这样带来的副作用是在某些情况下从库上可能短暂出现“已经过期但还能读到”的数据。Redis 7.0之后有了一些改进读取时会做逻辑过期判断让从库也能在读取路径上过滤掉过期key但底层删除依然由主库发起。另外从库默认是只读状态replica-read-only yes这个配置一定要保持开启。一旦把从库改成可写很容易出现主从数据不一致。比如有同事手贱在从库上执行了SET key value这个值只存在于从库本地主库和别的从库都不知道后面一旦发生切换这份数据可能要么丢失要么带着旧主库的数据冲突排查起来非常痛苦。所以我在搭建任何Redis主从环境时第一件事就是确认所有从库都是read-only。对了还有一个实用技巧如果从库数量特别多比如六个八个主库要给每个从库各生成一份全量RDB压力很大。你可以用级联复制的架构主库下面挂一个中转从库然后让其他从库同步这个中转从库而不是全部直接挂主库。这样主库只需要对一条链路负责成本低很多。这种拓扑叫主从级联非常适合主库写压力大且从库数量多的场景。3. 实操从裸机到Docker的一主两从搭建全流程3.1 手工配置Redis主从先搞清楚这几个关键项先走一遍最基础的裸机安装场景。假设你的Linux环境已经装好了Redis 7.x二进制和redis-cli都在PATH里。主节点的配置不需要大动只需要保证能接受来自从节点的连接并做基本持久化。我会给redis.conf加上如下配置bind 0.0.0.0 port 6379 protected-mode no requirepass yourmasterpass appendonly yes appendfsync everysec从节点的配置则多两行核心是指定主节点地址bind 0.0.0.0 port 6380 replicaof 127.0.0.1 6379 masterauth yourmasterpass replica-read-only yes这里有个细节容易被忽略如果主节点开了requirepass从节点必须配置masterauth否则认证不通过复制链路会反复报错日志里会出现NOAUTH Authentication required。我见过不止一个同事在容器环境里配了master密码却忘了在从库配masterauth结果主从关系一直起不来。启动主节点后再启动从节点。我习惯用前台方式启动便于看日志但生产环境一般用systemd接管。模拟一下手工启动# 主库 redis-server /etc/redis/redis-master.conf # 从库1 redis-server /etc/redis/redis-replica1.conf # 从库2 redis-server /etc/redis/redis-replica2.conf启动完成后登录任意从节点执行INFO replication你会看到类似下面的输出redis-cli -p 6380 -a yourmasterpass INFO replication输出关键部分# Replication role:slave master_host:127.0.0.1 master_port:6379 master_link_status:up master_last_io_seconds_ago:0 slave_repl_offset:123456master_link_status为up表示复制链路正常。如果这里显示down优先检查认证和网络连通性。3.2 Docker Compose方案一条命令拉起一主两从如果你跟我一样喜欢用容器做测试Docker Compose是最舒服的方式。新建一个docker-compose.yml内容参考这个version: 3.8 services: redis-master: image: redis:7.0 container_name: redis-master command: redis-server --appendonly yes --requirepass masterpass ports: - 6379:6379 networks: - redis-net redis-replica1: image: redis:7.0 container_name: redis-replica1 command: redis-server --replicaof redis-master 6379 --masterauth masterpass --appendonly yes ports: - 6380:6379 networks: - redis-net depends_on: - redis-master redis-replica2: image: redis:7.0 container_name: redis-replica2 command: redis-server --replicaof redis-master 6379 --masterauth masterpass --appendonly yes ports: - 6381:6379 networks: - redis-net depends_on: - redis-master networks: redis-net:这里有一个关键点容器之间用服务名redis-master通信。Docker Compose会为同一个网络里的服务自动做DNS解析所以从节点里的replicaof redis-master 6379不用关心主节点容器的IP是多少。如果你脱离Compose手动run容器就需要记得在docker run的时候指定同一个自定义网络并加--network-alias redis-master否则从节点找不到主节点。启动之后在宿主机上执行docker compose up -d docker compose exec redis-master redis-cli -a masterpass INFO replication你会在主节点这边的输出里看到connected_slaves:2以及两条slave0、slave1的信息每条都包含从节点的IP、端口、state和offset。只要offset两边一致且state是online就代表同步已经建立。3.3 验证同步是否真的生效很多人配完主从看日志一大片还是心里没底。我常用的验证方法是连上主节点写一个测试key再去从节点读一下redis-cli -h 127.0.0.1 -p 6379 -a masterpass SET sync_test hello-replica redis-cli -h 127.0.0.1 -p 6380 -a masterpass GET sync_test如果从节点返回hello-replica说明命令流已经到了。注意这一步只能证明“主写从读”通路正常还不代表延迟很低。想测主从延迟我一般再跑一个命令redis-cli -h 127.0.0.1 -p 6380 -a masterpass --latency -h 127.0.0.1 -p 6379严格来说redis-cli的--latency是测试客户端到服务端的网络延迟不是复制延迟。要精确看复制延迟应该在主节点执行INFO replication里面会显示master_repl_offset然后到从节点执行INFO replication看slave_repl_offset两个值的差值就是复制积压量。再结合主节点的写入速率可以大致估算复制延迟时间。生产环境中我更推荐用Prometheus redis_exporter监控这两个offset差值超过阈值自动告警。3.4 热配置修改主从关系搭建时用配置文件指定replicaof是一个办法但有时你需要临时调整主从关系比如切换主节点。Redis支持在线执行命令不需要重启进程。把当前实例变成某个主节点的从节点redis-cli -p 6380 -a masterpass REPLICAOF 127.0.0.1 6379把当前实例变成独立主节点redis-cli -p 6380 -a masterpass REPLICAOF NO ONE这个命令在故障转移时特别有用。注意执行REPLICAOF NO ONE后当前节点会保留已经同步的所有数据然后切换为主节点接受新的写请求这个动作是原子的不会丢数据。但是原本的主节点如果恢复后想重新加入集群你必须手动把它指向新主节点否则它会保持旧主的身份导致集群里出现双主。4. 读写分离与负载均衡的落地实践4.1 先想清楚你要分流的是什么流量主从复制最直接的价值之一就是读流量扩展。但必须明确一个边界Redis主从复制是不支持“写负载均衡”的。所有写命令最终都到主节点从节点只承担读流量。所以主从复制适合的是典型的读多写少场景比如热点数据查询、排行榜页、配置中心缓存、验证码验证等。我在业务中会把流量分类核心写入走主库所有只读操作按一定策略路由到从库。例如商品详情页的缓存读取、活动页的数据填充这类请求延迟敏感但允许很小的数据延迟而订单状态写入、用户积分变更这类操作则必须直接走主库。一般建议从库承担的读流量占总读流量的60%到80%剩下的20%到40%继续打主库目的有两个一是给主库保留读压力让主从切换时从库不会瞬间被峰值打爆二是保证强一致性的业务请求不因为复制延迟读到旧数据。4.2 客户端路由实践Python与Java两种写法读写分离最终要落实到客户端没有端到端打通架构图画得再漂亮都没有意义。我拿Python和Java分别写两个最简示例。Python使用redis-py库简单封装一个路由类import redis import random class RedisRouter: def __init__(self, master_host, replica_hosts, password): self.master redis.Redis( hostmaster_host, port6379, passwordpassword, socket_timeout3 ) self.replicas [ redis.Redis( hosth, port6379, passwordpassword, socket_timeout3 ) for h in replica_hosts ] def execute_write(self, command, *args): # 写命令永远走主库 return self.master.execute_command(command, *args) def execute_read(self, command, *args): # 读命令随机挑一个从库 replica random.choice(self.replicas) try: return replica.execute_command(command, *args) except Exception: # 从库故障时降级到主库 return self.master.execute_command(command, *args) router RedisRouter( master_hostredis-master, replica_hosts[redis-replica1, redis-replica2], passwordmasterpass ) # 写主库 router.execute_write(SET, user:1, tom) # 读从库 router.execute_read(GET, user:1)这个写法非常简单但已经包含了我认为最重要的两个设计点读请求随机路由和故障降级。从库如果挂了不能阻塞业务必须允许考虑降级到主库读取。当多个从库可用时随机或轮询都可以但我更推荐轮询加权避免某个从库瞬间被命中。Java端如果你的中间件还停留在Jedis裸连接阶段可以考虑用Lettuce的MasterReplica模式。Lettuce原生支持Redis主从拓扑的自动发现示例配置如下RedisClient client RedisClient.create(redis://masterpassredis-master:6379); MasterReplicaConnectionString, String connection MasterReplica.connect( client, new Utf8StringCodec(), RedisURI.create(redis://redis-master:6379) );这种模式下读命令可以配置优先走从节点而写命令仍然落到主节点。用Spring Data Redis的同学可以在redis配置里定义读写分离工厂类把LettuceConnectionFactory的执行顺序设成MasterReplica读取优先。4.3 从库脏读怎么办强一致性用例不要走从库主从复制默认是异步的主库执行写命令后命令进入复制缓冲再异步发送给从库。中间存在一个极短的延迟窗口。这个窗口有时是几百微秒但在网络抖动或从库负载高时也可能扩大到几十毫秒甚至更严重。因此如果你有一个场景要求“写完马上读并且必须读到刚才写入的数据”那这个读请求就不应该走从库。比如用户注册流程中校验码插入Redis后立即读取或者秒杀下单后需要读库存校验结果的场景这类强一致读必须直接打主库。我用一个简单原则数据一致性要求高、写后立读的关键路径全走主库允许最终一致的展示型数据才分流到从库。还有一个官方工具可以用WAIT命令。WAIT能阻塞当前客户端直到该命令引起的写操作被指定数量的从节点确认或者超时。原理有点接近半同步复制。但我不建议在核心路径上依赖WAIT因为它的成本不低而且降低了吞吐。你要做的应该是在业务架构层规避而不是靠命令兜底。4.4 主从复制最容易误用的几个场景首先是排行榜、库存扣减这类高频写操作。你如果把写请求平均分到所谓“主从多个节点”后果是这个key在每个节点上各写一份数据完全错乱。主从复制下的写负载均衡是伪命题写扩展需要靠Redis Cluster分片而不是复制。第二个误区是拿Redis主从做分布式锁。分布式锁要求强一致性的互斥判断而主从复制是异步的主库上锁刚被set还没同步到从库主库就宕机了从库被提升为新主库后根本不知道这把锁存在另一个客户端就可以成功加同样key的锁锁的安全就被破坏了。如果你必须用Redis做分布式锁官方文档也提到过需要仔细权衡业界一般有Redlock方案但它本身也有争议。我个人的建议是如果是金融支付等高价值系统分布式锁请选择etcd或ZooKeeper这类强一致组件如果是普通业务场景能容忍极端情况下锁失效再考虑Redis方案并做兜底。第三个误区是无限增加从库做读扩展。每个从库都要全量同步主库需要fork子进程生成RDB内存和磁盘都会被顶起来。所以当我需要大量读副本时我更倾向先做一主三从然后任一从库再挂一层级联而不是把十来个从库全挂在主库下面。5. 从主从复制到高可用体系哨兵和集群怎么接5.1 手工故障转移的一次完整操作在接入哨兵之前我想先让你明白没有自动化切换的时候运维要面对什么。假设主节点6379所在机器宕机了此时两个从节点6380和6381上的数据还在但客户端仍然连6379业务已经写不进去。手工切换的标准步骤是先选一个数据最新的从节点。判断依据是INFO replication里的slave_repl_offset哪个跟原主节点断开时的master_repl_offset差距最小哪个就最新。登录到选中的从节点执行redis-cli -p 6380 -a masterpass REPLICAOF NO ONE然后确认这个节点角色已经变成masterredis-cli -p 6380 -a masterpass INFO replication # 此时 role 应该变成 master接下来把另一个从节点重新指向新主节点redis-cli -p 6381 -a masterpass REPLICAOF 127.0.0.1 6380最后改客户端连接池把主库地址从6379切成6380。如果是线上业务我一般配合配置中心或者环境变量做热更新然后在低峰期把原主节点重新加回来。这一套流程熟练的话两三分钟内能完成但前提是你提前演练过否则等到故障真的发生时人一慌什么都会忘。5.2 哨兵模式自动故障转移的关键手工切换只能应急生产环境必须上Sentinel。Sentinel本质上是一个独立的Redis进程它不停PING各个数据节点监测主从状态。当主节点被判定故障后Sentinel之间会协商并选择一个从节点提升为新主节点然后通知其他从节点重新完成重定向还会把一个叫做“当前主节点地址”的配置信息写入所有Sentinel节点。我常用的最小sentinel配置如下sentinel monitor mymaster 127.0.0.1 6379 2 sentinel auth-pass mymaster masterpass sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 10000第一行表示监控一个名为mymaster的主节点地址为127.0.0.1:6379需要2个Sentinel实例同时认为主节点不可达才会触发故障转移。这里有个关键点Sentinel本身必须至少有3个实例或奇数个否则无法满足“多数票决定”的前提。2个Sentinel是不安全的万一其中一个挂了剩下的那一个永远无法达到法定人数。哨兵模式的客户端一般会用Redisson或Spring Data Redis它们支持从Sentinel获取当前主地址自动实现故障转移时的重连。我在生产环境中的经验是Sentinel放在独立的低峰机器至少3个不能和数据节点混部在同一台物理机否则这台机器一挂数据节点和哨兵同时失联整个系统的自我恢复能力就归零了。5.3 Redis Cluster写扩展才是主从的终极形态当你的数据量大到单机内存扛不住或者写请求也到了单主节点瓶颈时就要上Redis Cluster了。Cluster把数据按照16384个槽位做分片每个数据key通过CRC16算法映射到某个槽位每个主节点负责一部分槽位。而每一个主节点仍然可以挂若干从节点从节点负责主节点故障时的自动切换和数据冗余。换句话理解Cluster是“分片 主从复制 自动故障转移”的组合体。从节点在Cluster里不仅提供了冗余还承接了读流量的分担。这种架构天然就解决了主从模式下写扩展无解的问题因为多主之间可以分摊不同key的写压力。但Cluster也带来更多约束。比如涉及多个key的MGET操作如果这些key不在同一个槽位上就不能在一次命令中完成。官方建议使用Hash Tag机制把相关的key强制放到同一个槽位。对业务侵入比较大所以如果你的数据量根本不到几十GB我不建议一上来就上Cluster先玩好一主多从和哨兵性价比高得多。6. 常见问题与排查实录6.1 从库一直显示down到底卡在哪一步最常见的主从建不上原因有四个认证不匹配、防火墙端口不通、replicaof写错地址、以及主从版本差距过大。排查时可以遵循这个顺序先看从库日志如果出现Unable to connect or authentication failed那就从认证入手。如果日志一直停在Full resync request和Background RDB transfer说明网络层面没问题可能是全量同步数据传输被防火墙卡住大包或者主节点到从节点的带宽被占满。如果日志中反复出现Cannot determine the database size大概率是磁盘空间不足RDB生成失败。另外一个容易忽略的是Linux内核参数tcp keepalive。连接空闲一段时间后可能被中间设备切断从库会频繁尝试重连。建议在两边的sysctl.conf里设置net.ipv4.tcp_keepalive_time60net.ipv4.tcp_keepalive_intvl15能减少大量无谓的断连重连。6.2 全量同步反复发生主库CPU飙高如果从库老是发生全量同步基本上就是PSYNC部分同步失败。核心原因在于主节点复制积压缓冲区太小从节点落后太多退出重连时offset已经不在缓冲区里。处理思路有两步第一步调大repl-backlog-size。我建议不要低于256MB同时观察主节点内存确保没有因为缓冲区过大触发内存压力。第二步排查从节点为什么总是落后太多。常见原因是从节点CPU资源被挤占或者从节点上跑了一些非常耗时的命令比如KEYS *、SUNION大集合、SORT大列表等这些命令会阻塞从节点主线程导致复制命令处理不过来延迟一路飙升。解决方法是优化业务代码禁止在Redis上执行全库匹配和重排序从库也一样不能跑。如果从库数量太多主节点fork生成RDB频繁也容易触发CPU飙高。此时建议启用repl-diskless-sync yes甚至做一个级联架构减少主节点的fork压力。6.3 主从延迟越来越高怎么办先看两个指标master_last_io_seconds_ago和slave_repl_offset差。master_last_io_seconds_ago如果持续超过10秒说明从库很久没跟主库有IO交互了大概率是链路中断或者从库主线程阻塞。如果offset差值持续变大说明从库正在消费复制流但赶不上需要排查从库负载和网络带宽。针对网络本身可以查看主从两端网卡是否有大量重传和丢包。我在实际环境里遇到过从库部署在公网跨地域的场景延迟和丢包惨不忍睹主从offset始终追不平。后来硬是让业务方把从库迁到同机房同可用区问题才消失。主从复制对网络质量的要求是硬性的跨地域部署请慎重尽量只做跨机房的异步备份不要指望跨地域从节点承担实时读流量。6.4 一张表总结典型故障现象典型原因处理顺序主从关系建不起来认证、网络、版本不匹配日志 → ping → auth → replicaof调整全量同步反复触发backlog过小、从库太慢调大backlog、优化从库命令、考虑级联主从延迟持续增长网络丢包、从库阻塞、大key同机房部署、清理慢命令、拆分大key切换后部分客户端报错客户端没感知新主地址配置中心热更新、接入Sentinel/Cluster发现主从数据不一致从库被写入、过期逻辑、手动改库强制read-only、禁止人工改数据、重建同步主库内存突然升高多个从库全量同步、fork COWdiskless复制、级联、错峰扩容老实说这张表不足以覆盖所有奇奇怪怪的生产故障但它能帮你把80%的日常问题框到一个合理排查路径里。Redis主从复制的坑大部分都在“缓冲区、网络、阻塞、异步延迟”这四个关键词上抓住它们排查方向就有了。最后再说几句大实话从我几年下来的实操体会来看主从复制本身并不难搭建难的是你搞清楚它到底为你扛下了什么、又留下了什么空白。它能帮你把读流量分散开能让你在硬件故障面前多一份数据副本但它不会自动做主节点切换也救不了你在旧主上执行的FLUSHALL更别指望它在极端情况下还能维持分布式锁的绝对安全。真正成熟的做法是这样的核心业务读多写少且能容忍最终一致性先用一主两从做读写分离数据一致性要求高的路径直接走主库再叠加3个Sentinel做自动故障转移等数据量到了几十一百GB、写压力也有明显瓶颈时再认真评估Redis Cluster。每一步我都在实际业务里跑过这条路虽然不算快但稳。