Redis主从复制还是Cluster?容量与写扩展才是分水岭
2026/9/6 1:58:31 网站建设 项目流程

很多人学完 Redis 主从复制,就会产生一个疑问:主节点挂了能从节点顶上,读压力大了还能挂从节点分担,那为什么还要 Redis Cluster?这个疑问在面试里经常出现,实际项目里也经常被误用。先说结论:主从复制解决的是高可用和读写分离问题,Redis 集群解决的是容量扩展和写扩展问题。两者解决的问题不一样,所以不是“谁替代谁”,而是不同层次的事。如果只做主从复制而不上集群,在单机内存和单点写能力到达上限时,照样会卡死。下面从原理、场景和实操选择三个方面完整拆一遍。

1. 先搞清楚:主从复制到底解决了什么问题

1.1 主从复制的本质是数据冗余加读写分离

Redis 主从复制的基本结构是一个主节点带多个从节点。主节点负责写请求,从节点负责读请求,数据从主节点异步同步到从节点。这个架构解决了两类问题:

第一是单点故障。主节点挂了,从节点可以顶上,前提是你手动切换,或者部署了哨兵机制。没有哨兵的话,主从复制本身不会自动把从节点升级成新的主节点,这一点要特别注意。

第二是读压力。如果你的业务是典型的读多写少,比如缓存热点数据、商品列表、用户会话,那么一台主节点扛不住大量读请求时,多加几个从节点,把读流量分散下去,效果立竿见影。

从这个角度看,主从复制是 Redis 高可用体系的第一层防护,成本低、配置简单、理解容易。很多小团队从单机升级到主从复制,稳定性已经提升了一大截。

1.2 主从复制的两个硬边界:单机容量和单点写能力

但主从复制没有改变一个事实:所有写请求仍然集中在主节点上。无论你挂了多少个从节点,写入路径始终只有主节点一条。这带来两个硬边界。

第一个边界是容量。主节点是单台机器,内存上限受物理资源限制。一台 64GB 内存的机器,就算配了 Redis 的 maxmemory,实际能用的数据空间也就是 50GB 到 60GB 左右。当业务缓存数据超过单机内存时,主从复制解决不了扩容问题。你加从节点,从节点的数据也是从主节点全量复制过来的,总量并没有拆分。

第二个边界是写吞吐。主节点要承接所有写命令、处理持久化、再把数据同步给所有从节点。如果写请求本身就到了每秒几万甚至十万级别,主节点的 CPU 会率先成为瓶颈。此时加从节点分担不了写压力,反而会增加主节点的同步开销。

我在实际排查过一个项目,主从配置看起来没有问题,但主节点 CPU 经常冲到 90% 以上。后来发现写 QPS 已经接近单机上限,从节点读流量又大,主节点一边处理写请求,一边全量或增量同步到多个从节点,网络和 CPU 双双被打满。这种情况就是典型的主从架构已经到边界的信号。

注意:主从复制解决的是“单点故障”和“读扩展”,不解决“容量扩展”和“写扩展”。判断是否需要集群,先看这两个指标有没有逼近上限。

2. 主从复制扛不住的三类真实场景

2.1 数据量超过单机内存时,主从复制无能为力

很多团队把 Redis 当成缓存用,以为设置了过期时间就不会有内存问题。但实际线上经常出现两种情况。

一种情况是热点数据太多,内存不断膨胀。比如做了商品详情缓存、用户行为缓存、配置缓存,每一个 key 都设置了过期时间,但总量仍然超过单机内存。此时 Redis 会用淘汰策略删除不常用的数据,导致缓存命中率下降,大量请求穿透到数据库。

另一种情况是数据必须全量留存,不能随意淘汰。比如做实时排行榜、分布式锁记录、限流计数,部分 key 不能设过期时间。这时候内存压力会持续增长,主从节点都保存同一份全量数据,等于一台机器装不下,再多从节点也帮不了忙。

要解决容量问题,必须把数据分散到多台机器上。每个节点只存一部分 key,这才叫分片。Redis Cluster 做的事情就是分片。所以当你的数据集预期会超过一台机器内存时,主从模式就不够用了。

2.2 写请求成为瓶颈时,加从节点反而帮倒忙

读多写少的场景下,加从节点分担读流量很有效。但写多读少的场景下,比如秒杀扣减库存、热点计数、消息队列、实时流计算,写 QPS 很高,主节点的 CPU 会成为瓶颈。

更麻烦的是,主从复制是有同步开销的。主节点处理每个写命令之后,还要把命令传播到所有从节点。从节点越多,主节点的网络输出和同步成本越大。在高写入压力下,多加从节点不仅不能分担主节点压力,还可能让主节点的延迟明显上升。

我建议判断是否需要集群时,重点看两个指标:写 QPS 是否超过单机上限,主节点 CPU 是否长期在 70% 以上。如果两个条件同时成立,就该考虑把写流量也分散到多个节点上。

Redis Cluster 的分片机制让每个主节点只负责一部分 key。写请求会根据 key 的哈希结果路由到对应节点,每台机器承担的写压力就降下来了。这是主从复制做不到的。

2.3 故障切换要求高时,主从复制不是完整的高可用方案

还有一个容易被忽略的问题。纯主从复制模式下,主节点发生故障后,从节点不会自动接管,需要人工介入。即使配合哨兵模式,故障切换过程中涉及选举、配置更新、客户端重连,整个过程也不是零配置的。

哨兵解决了自动故障切换的问题,但在数据量和写压力已经很大的场景下,即使切换成功,新的主节点还是单机写能力,容量和性能瓶颈依然存在。哨兵只是保证可用性,不保证扩展性。

集群模式下,故障转移是自动的。某个主节点挂了,它下面的从节点会通过选举升级为新的主节点,客户端请求会重新路由到新节点。整个集群仍然有多个主节点在对外服务,单点故障的影响面更小。

3. Redis Cluster 到底比主从复制多做了哪些事

3.1 数据分片:把 key 分散到多个主节点

Redis Cluster 采用哈希槽机制,整个集群有 16384 个槽位。写入一个 key 时,客户端通过对 key 做 CRC16 计算,再对 16384 取模,得到这个 key 属于哪个槽,然后路由到对应的主节点。

集群默认配置下,每个主节点负责一部分槽位。比如 3 个主节点的集群,槽位分配可能是 0 到 5460、5461 到 10922、10923 到 16383。这样每个节点只保存全量数据的一部分。

数据分片带来了两个直接收益:

第一,容量可以水平扩展。数据量大了,往集群里加主节点,重新分配槽位,每个节点的内存压力就会下降。整个过程不需要停止服务。

第二,写压力被分散到多个节点。每个节点的写命令只涉及它负责的槽位,单节点的写负载上限被抬高。

有一个细节需要注意:Redis Cluster 的最小规模通常是 3 个主节点。原因是槽位要尽量均匀分配,而且故障转移时需要投票选举,至少 3 个节点才能形成多数派。如果只搭两个主节点,某个节点故障后可能无法完成可靠选举。

3.2 自动故障转移:从节点升级和多节点投票

Redis Cluster 的每个主节点都可以配置从节点。主节点故障后,集群会检测到节点不可达,然后从该主节点的从节点里选举一个升级为新的主节点。

选举过程依赖集群内部节点之间的心跳消息。Gossip 协议会持续交换节点状态,当某个主节点在一段时间内无法被大多数节点访问,就会被标记为故障。集群会从它的从节点中选出优先级最高的,提升为新的主节点,并接管原来的槽位。

这个机制比哨兵模式更贴近 Redis 自身的数据结构。哨兵是独立于 Redis 的外部进程,需要额外部署和维护。集群的故障转移逻辑内建在 Redis 节点中,不需要额外组件,但复杂度转移到了配置和运维层面。

3.3 客户端路由:MOVED 和 ASK 的处理逻辑

集群模式下,客户端不能像单机那样随意连接任意节点执行命令。客户端需要知道每个 key 对应的槽位由哪个节点负责。

当客户端向错误的节点发送指令时,节点会返回一个 MOVED 错误,告诉客户端正确的节点地址。比如执行SET user:1001 name zhangsan,结果槽位不在当前节点,节点会返回MOVED 12780 192.168.1.10:6379,客户端需要重新连接后再执行。

ASK 错误出现在槽位迁移过程中。当集群在做扩容或缩容时,部分槽位可能正在从旧节点迁移到新节点。客户端访问一个正在迁移的槽位,旧节点如果已经查不到数据,就会返回 ASK,要求客户端转向新节点查询。

所以生产环境使用集群,一般不推荐自己解析 MOVED 和 ASK,而是直接用官方推荐的客户端,比如 redis-py-cluster、JedisCluster、Lettuce。这些客户端内置了槽位缓存和重定向逻辑,用户只需要配置节点列表,其余由客户端处理。

注意:如果你的客户端不支持集群协议,即使服务端搭好了集群,也会频繁遇到跨节点读写失败的问题。选客户端时先确认它是否支持 Redis Cluster 模式。

4. 主从复制和集群不是二选一,集群内部也有主从

4.1 Cluster 的每个分片本身就是一个主从结构

很多人会把主从复制和集群对立起来,觉得项目要么做主从,要么做集群。实际上 Redis Cluster 内部仍然依赖主从复制。

集群里的每个主节点都可以挂一个或多个从节点。主节点负责处理该分片的读写请求,从节点作为主节点的数据副本。主节点故障后,从节点接管并变成新的主节点。所以集群模式并没有抛弃主从复制,而是在主从复制之上增加了一层分片路由。

我更喜欢把 Redis Cluster 理解成“多组主从复制组成的分片架构”。每一组主从解决局部高可用问题,整个集群解决全局容量和写扩展问题。两者是叠加关系,不是替代关系。

4.2 主从模式适合什么规模,集群模式适合什么规模

如果业务处于以下阶段,主从模式完全够用:

  • 数据总量在单机内存的 50% 到 60% 以内,未来两年不会翻倍。
  • 写 QPS 在单机承受范围内,比如一秒钟几千到一两万。
  • 读压力可以通过增加从节点横向扩展。
  • 团队没有专门的 Redis 运维经验,追求简单可靠。

如果出现以下信号,就该考虑集群:

  • 数据量已经超过单机内存,或者预计半年内超过。
  • 写 QPS 接近单机上限,主节点 CPU 长期高于 70%。
  • 需要不停机扩容。
  • 单个业务故障的影响面要求尽量小,不能在主节点挂掉后停写太久。

具体量化数字会因机器配置不同有差异,但思路是一致的:主从模式适合“数据总量受控、写流量平稳”的阶段,集群模式适合“数据量持续增长、写并发明显走高”的阶段。

4.3 集群最少需要几台机器,配置怎么规划

Redis Cluster 最简配置是 3 个主节点,没有从节点。这个配置可以满足集群的基本功能,但高可用没有保障。某个主节点挂了,它负责的槽位就没有节点接管,这部分数据会不可用。

更稳妥的配置是 3 个主节点加 3 个从节点,每个主节点挂一个从节点。一共 6 个 Redis 实例,可以部署在 3 台物理机或虚拟机上,每台机器跑一主一从。这样做的好处是某一个物理节点挂掉,集群可以跨机器完成故障转移。

如果是小规模试验,也可以用一台机器跑多个实例,分别映射不同端口。不过这只适合学习验证,生产环境不推荐,因为单机多实例没有解决物理机故障问题,数据都落在同一块磁盘上。

5. 从主从复制迁移到集群时,最容易被坑的几个点

5.1 多 key 操作在集群里变成了受限操作

这是从主从迁移到集群时最明显的差异。主从模式下,所有 key 都在同一个 Redis 实例上,MGETMSETSUNIONSTORE、事务块、Lua 脚本可以轻松操作多个 key。

集群模式下,不同 key 可能落在不同节点上。客户端对多个 key 执行跨槽操作时,如果这些 key 的槽位分布在多个主节点上,Redis 无法在一个节点上完成原子性操作。结果就是部分命令不再直接可用,或者需要满足特殊条件才能在同一个节点上执行。

解决办法之一是使用 hash tag。Redis Cluster 在计算槽位时,如果 key 里包含花括号,比如user:{1001}:nameuser:{1001}:age,哈希计算只针对花括号里的内容。只要花括号里的值相同,这两个 key 就会落在同一个槽位,也就能够在同一个节点上做多 key 操作。

但 hash tag 不要滥用。如果把大量 key 都放在同一个 tag 下,会导致数据集中在一个节点上,破坏分片的均匀性。一般只对确实需要原子操作的关键数据使用。

5.2 客户端连接方式和命令行为发生变化

主从模式下,客户端通常连接到主节点写、从节点读。集群模式下,客户端需要连接到集群节点列表,客户端会自动感知集群拓扑。

有的客户端需要配置节点发现地址,有的客户端支持自动发现并更新槽位映射。配置不当会导致连接失败或请求重定向过多。常见问题是只填了一个节点地址,而且该节点挂了,客户端没有其他节点可以连接,导致整个应用报错。建议至少配置两个或三个节点地址,提升容错性。

另外,SELECT命令在集群模式下也是不可用的。集群模式只支持 db0,因为数据分片和数据库编号是两个维度的概念,集群没有办法保证非 db0 数据库的数据均匀分布。迁移到集群前,先检查代码里有没有使用SELECT 1这类操作。

5.3 数据迁移不是简单的复制和切换

从主从模式迁移到集群,不能直接把 dump.rdb 文件丢到集群节点上启动。集群模式下,每个节点只保存一部分槽位数据,节点启动后会检查自身槽位和集群槽位分配是否一致。

正确的迁移思路是先配置好集群,让集群运行起来,再通过数据同步或复用主从同步机制把数据导入。实际操作时,可以使用 Redis 官方推荐的工具或者中间件完成迁移,但要提前做好验证。

我做迁移时习惯分四步走:

  1. 先在测试环境搭一套同样配置的集群,模拟全量数据写入。
  2. 使用客户端做数据双写或离线导入,验证数据一致性。
  3. 观察集群槽位分布是否均匀,各节点内存占用是否接近。
  4. 确认无误后,在低峰期切换读写流量。

不要在生产环境直接做“一把梭”式迁移,尤其是数据量超过几十 GB 时,先做容量评估和槽位规划,再执行操作。

5.4 Pipeline 和事务在集群下的行为变化

Pipeline 在集群模式下仍然可以用,但要注意同一个 Pipeline 里的多个 key 可能落在不同节点上。客户端在发送 Pipeline 时会先计算每个 key 的槽位,然后把相同槽位的命令打包发到对应节点。不同节点上的 Pipeline 会被拆成多条请求。

事务方面,MULTIEXEC只保证单个节点上的原子性。如果事务里的多个 key 分布在不同节点,Redis Cluster 无法保证这些操作的全局原子性。Lua 脚本也有同样的限制。

需要事务保证又必须跨节点时,可以考虑业务层补偿机制,或者换用支持分布式事务的存储方案。不要指望 Redis Cluster 能解决跨节点原子操作问题。

6. 如果没有一上来就上万 QPS,其实不一定要急着上集群

6.1 判断是否需要集群的量化标准

很多团队一听到“性能瓶颈”四个字,就想着上集群。但集群引入之后,客户端配置、数据分片、运维监控、扩容收缩,复杂度都比主从模式高出一个量级。

我更建议用几个量化标准来做判断:

  • 数据量:当前数据总大小是否接近单机内存的 70%。如果是,且增长趋势明显,准备上集群。
  • 写 QPS:主节点写 QPS 是否长期超过单核处理能力。Redis 单线程模型下,写命令密集时 CPU 会成为瓶颈,一般几万写 QPS 就需要密切关注。
  • 读 QPS:读请求是否可以通过增加从节点解决。如果从节点已经加到 3 个,读压力仍然高,说明单组主从架构已经顶不住,考虑集群。
  • 故障恢复时间:主节点挂掉后,业务是否允许几分钟的不可用。如果要求秒级恢复,集群的自动故障转移更合适。

这些标准没有绝对数字,因为机器配置、命令复杂度、key 大小都会影响结果。但思路是通用的:先量化当前压力,再判断架构是否需要升级。

6.2 单主多从已经把大多数缓存场景扛住了

很多企业级应用其实并没有到必须上集群的阶段。比如典型的电商缓存场景,商品详情、用户信息、配置数据,总量在 10GB 到 20GB 之间,读 QPS 几千到上万。这种场景下,一个主节点加两个从节点,配合哨兵做自动故障切换,已经足够稳定。

多从节点分担读流量,主节点专注于写请求,哨兵负责故障切换。这套组合比直接上集群简单得多,部署、监控、排查成本都要低。

如果你是在学习阶段,可以先用一个主节点加两个从节点做实验,把复制原理、全量同步、增量同步、故障切换全搞清楚。然后把主从复制迁移到集群,你会更容易理解为什么集群需要槽位分配、为什么多 key 操作受限。

6.3 如果你的场景真的需要集群,执行顺序是什么

如果真的需要上集群,我建议按下面顺序推进:

  1. 先评估当前数据量,确定集群需要多少个主节点。一般从 3 个主节点起步。
  2. 规划物理机或虚拟机分配,每个主节点至少配一个从节点。
  3. 搭建集群并确认槽位分配均匀。
  4. 配置客户端,使用支持集群模式的客户端连接。
  5. 做功能测试,重点检查多 key 操作、Pipeline、事务、Lua 脚本的兼容性。
  6. 执行数据迁移,先迁移测试数据,再迁移全量数据。
  7. 低峰期切换流量,观察一段时间确认稳定。
  8. 建立监控,关注各节点内存、CPU、网络、命中率和故障转移事件。

最后留一个个人判断:如果主从复制还没有触及单机容量或写吞吐的边界,不要为了追新而上集群。等真的出现容量写不下或者写压力打满主节点时,再按上面的顺序做平滑迁移。架构升级不应该是提前焦虑,而是发现明确瓶颈之后做出的自然选择。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询