一台 Redis 撑不住数据量的时候怎么办?很多团队的第一反应是上主从复制,但其实主从模式只是解决了高可用和读扩展问题,每台机器依然保存全量数据,内存天花板并没有被打破。真正要把数据量水平拆分出去,让每个节点只保留一部分数据,你需要的是一套分片集群机制。这篇以 Redis Cluster 为主线,把分片集群的数据读写规则彻底讲透:key 和数据到底怎么分布到不同的节点上,客户端如何找到正确的节点,扩容缩容、故障转移时读写路径又会发生什么变化。如果你是准备面试,把这里的读写规则搞懂基本能讲清楚整体原理;如果你是要在生产环境落地集群,后面几章的实操和迁移经验同样可以直接参考。
1. 分片集群真正要解决的是“单机瓶颈”问题
1.1 单机、主从、哨兵模式各自的天花板
很多人在面试里被问到“为什么要用分片集群”时,第一反应是“为了高可用”。这个答案其实不太准确。分片集群的核心动机,是单机已经装不下、也扛不住了。
单机 Redis 的问题最直接:数据全在一个进程里,内存上限受机器物理内存限制,CPU 也被单线程模型锁死。数据量只要超过单机内存,除了加大内存外没有别的办法,而且一台机器挂了整份缓存就没了。
主从复制解决的是读扩展和基础可用性,它让从节点持有主节点的全量副本,可以把读请求分摊到多个节点。但它的容量并没有扩大,从节点有多大内存,主节点还得有多大内存,全量副本意味着数据量只受限于单机容量。更关键的是,主从模式的主节点仍然是单点写入,写 QPS 上不去,内存天花板也没变。
哨兵模式是在主从架构上加了自动故障切换,能在主节点宕机时自动把从节点提升为新主节点。它解决的是“主节点挂了怎么办”的问题,但容量和写吞吐的瓶颈依旧。
| 模式 | 解决的核心问题 | 没有解决的问题 | 数据存储 | 适用场景 |
|---|---|---|---|---|
| 单机 | 基本缓存读写 | 容量、高可用、写瓶颈 | 全量 | 数据量小、允许宕机直接不可用 |
| 主从复制 | 读压力、基础冗余 | 自动切换、容量上限、写瓶颈 | 全量副本 | 读多写少,单机内存够用 |
| 哨兵 | 自动切换、高可用 | 容量上限、写瓶颈 | 全量副本 | 需要自动切换的主从架构 |
| 分片集群 | 容量水平扩展、写吞吐、高可用 | 运维复杂度、多 key 限制 | 数据分片 | 数据量超过单机容量或写并发过高 |
这四种模式的本质区别就一句话:前三种都是“多存一份”,分片集群是“拆开存”。
1.2 分片(sharding)是“拆开存”,不是“多存一份”
分片集群的思想很简单:一台机器装不下,就多台机器一起装,每台只负责一部分数据,合起来对外提供一个完整的 Redis 服务。
打个比方,一家书店从一个人管理变成六个管理员管理,每个人负责一排书架。顾客来借书时,前台根据书名计算这本书应该在哪排书架上,然后告诉顾客去找哪个管理员。这个“前台”在 Redis 集群里就是槽位规则 + 客户端路由。
Redis Cluster 里分片的最小单位不是 key,而是 16384 个槽位。每个 key 都会通过哈希计算映射到一个槽位,槽位再被分配到具体的节点上。为什么不是直接按 key 分片?因为 key 的数量是动态变化的,直接绑定 key 会导致加机器时需要重新计算大量 key 的位置;而槽位是固定数量、固定编号,数据只是绑定到槽位上,槽位分给谁可以灵活调整。这样一来,扩容时只需要把一部分槽位从老节点迁到新节点,迁移粒度可控,客户端路由规则也清晰。
所以理解分片集群,本质上是理解三件事:key 怎么映射到槽位、槽位怎么分配给节点、节点挂了之后怎么切换。接下来一节