什么是 Redis 的数据分片?

一则或许对你有用的小广告

欢迎 加入小哈的星球 ,你将获得: 专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新开坑项目: 《Spring AI 项目实战(问答机器人、RAG 增强检索、联网搜索)》 正在持续爆肝中,基于 Spring AI + Spring Boot3.x + JDK 21...点击查看;
  • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot3.x + JDK 17...点击查看项目介绍; 演示链接: http://116.62.199.48:7070/;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/

面试考察点

  1. 概念理解:面试官不仅仅是想知道 "数据分片" 这个名词,更是想知道你是否清楚 为什么需要分片(单机瓶颈:内存、QPS、带宽),以及分片的核心思想(把数据分散到多个节点)。

  2. 方案掌握度:考察你是否了解 Redis 数据分片的 多种实现方式(客户端分片、代理分片、服务端分片),以及各自的优缺点和适用场景。

  3. 原理深度:能否说清楚 Redis Cluster 的 Hash Slot 路由机制CRC16(key) % 16384),以及 MOVED/ASK 重定向、Hash Tag 等核心机制。

核心答案

Redis 数据分片是指 将数据按照一定规则分散存储到多个 Redis 节点上,从而突破单节点的内存、QPS 和网络带宽限制。

分片方式代表方案路由位置优点缺点
客户端分片ShardedJedis / 自定义客户端无代理,性能高节点变更需重启
代理分片Twemproxy / Codis代理层对客户端透明多一跳,代理是瓶颈
服务端分片Redis Cluster服务端官方方案,自动管理迁移成本高,有限制

一句话结论:数据分片是解决 Redis 单机瓶颈的关键手段。早期用客户端分片或 Twemproxy/Codis 等代理方案,现在 Redis Cluster(服务端分片)是主流方案,通过 16384 个 Hash Slot 实现自动分片和故障转移。

深度解析

一、为什么需要数据分片?

上图说明了为什么需要数据分片:

  • 内存上限:单台 Redis 通常只能装几十 GB 数据,数据量超过单机内存时就装不下了。
  • QPS 上限:单节点大约能承受 8~10 万 QPS,超过这个量级单机扛不住。
  • 网络带宽:单节点网卡带宽有限,大 Value 场景下网络可能先成为瓶颈。
  • 解决思路:把数据按照规则分散到多个节点上,每个节点只存一部分数据,从而实现 内存、QPS、带宽的线性扩展

二、分片方式一:客户端分片

上图展示了客户端分片的架构:

  • 路由逻辑在客户端:客户端根据 key 计算 hash 值,决定请求发到哪个 Redis 节点。常见算法是 hash(key) % N(N 是节点数)。
  • 优点:没有代理层,客户端直连 Redis,性能最高。
  • 缺点:分片逻辑耦合在业务代码中,运维不便。节点增减需要修改客户端配置并重启应用,没有自动故障转移能力,需要自己搭建 Sentinel 等方案来保证高可用。
  • 代表方案:ShardedJedis、自定义分片逻辑。属于早期方案,现在已较少使用。

三、分片方式二:代理分片

上图展示了代理分片的架构:

  • 路由逻辑在代理层:客户端只需要连接代理,代理负责接收请求、计算 hash、路由到后端 Redis 节点、返回结果。客户端完全不需要关心分片逻辑。
  • 优点:对客户端透明,运维友好,代理层统一管理。
  • 缺点:多了一跳网络开销(客户端 → 代理 → Redis),代理层本身可能成为性能瓶颈,也需要保证高可用。
  • Twemproxy vs Codis:Twemproxy 是 Twitter 开发的,轻量但不支持在线扩容和自动故障转移;Codis 是豌豆荚开发的,功能更完善(支持在线扩缩容、自动故障转移、有管理界面),但两者都已被 Redis Cluster 逐渐取代。

四、分片方式三:Redis Cluster(服务端分片)

这是 Redis 官方的分片方案,也是目前生产环境的主流选择。

上图展示了 Redis Cluster 的分片架构:

  • 16384 个 Hash Slot:Cluster 将整个 key 空间划分为 16384 个 slot,平均分配给各个 Master 节点。每个 Master 负责一部分 slot。
  • 路由规则:客户端发送命令时,对 key 做 CRC16(key) % 16384 计算 slot 编号,然后路由到负责该 slot 的 Master 节点执行。
  • 去中心化:没有代理层,客户端直连 Redis 节点。节点之间通过 Gossip 协议通信,没有中心节点。
  • 高可用:每个 Master 配备至少一个 Slave,Master 宕机时 Slave 自动晋升。
  • 在线扩缩容:可以通过 CLUSTER SETSLOT 命令迁移 slot,实现不停机扩缩容。

五、Cluster 的路由机制

上图展示了 Cluster 的四种路由场景:

  • 正常路由:客户端直接请求到了正确的节点,直接执行并返回结果。智能客户端会缓存 slot → node 的映射关系,大部分请求都能直接命中。
  • MOVED 重定向:客户端请求到了错误的节点,该节点返回 MOVED 指令,告诉客户端正确的节点地址。客户端更新本地缓存,下次直接路由到正确节点。MOVED 表示 slot 已经 永久迁移
  • ASK 重定向:slot 迁移过程中,请求到了源节点但 key 已迁移到目标节点。源节点返回 ASK 做临时重定向。ASK 不会更新客户端的 slot 映射缓存,因为迁移还没完成。
  • Hash Tag:用 {tag} 语法强制多个 Key 落在同一 slot。只有 {} 内的部分参与 hash 计算。这样 {user:1001}:name{user:1001}:age 会在同一 slot,可以进行 MGET 等多 Key 操作。

六、三种分片方式对比

上图对比了三种分片方式的核心差异:

  • 客户端分片:性能最高但运维最复杂,不适合生产环境。
  • 代理分片:对客户端透明,Codis 功能完善,但多了一跳开销且非官方方案,已被 Cluster 逐渐取代。
  • Redis Cluster:官方方案,去中心化,支持在线扩缩容和自动故障转移,是 新项目的首选

面试高频追问

  1. 追问一:为什么 Cluster 用 16384 个 slot,而不是 65536 或其他数字?

    核心原因是 Gossip 协议的心跳包大小。节点之间定期交换 slot 映射信息,16384 个 slot 只需 2KB 的 bitmap 就能表示。如果用 65536 个 slot,bitmap 就需要 8KB,心跳包变大,浪费带宽。此外 Redis 作者 antirez 认为集群节点超过 1000 个时性能就不理想了,16384 完全够用。

  2. 追问二:Cluster 扩缩容时数据怎么迁移?

    扩容时,先加入新节点,然后从现有节点 迁移部分 slot 到新节点。迁移过程中使用 ASK 重定向保证请求正常路由。缩容则反过来,先把 slot 迁走再下线节点。整个过程中集群正常服务,不会停机。

  3. 追问三:客户端分片中 "一致性哈希" 和 "取模" 有什么区别?

    取模(hash(key) % N)在节点数 N 变化时,大部分 key 的映射关系都会改变,导致大面积缓存失效。一致性哈希将节点映射到 0~2^32 的环上,key 也映射到环上,顺时针找最近的节点。增减节点时只影响相邻节点的数据,迁移量小。Redis Cluster 没有使用一致性哈希,而是用了 固定 slot 数(16384)+ 哈希取模,因为 slot 数固定不变,节点变化只影响 slot 的归属映射。

常见面试变体

  • 变体一:"Redis Cluster 的路由机制是怎样的?"
  • 变体二:"Redis 的 16384 个 slot 是怎么来的?"
  • 变体三:"一致性哈希和 Hash Slot 有什么区别?"
  • 变体四:"Codis 和 Redis Cluster 怎么选?"

记忆口诀

分片三种方式:客户端(最快但最累)→ 代理(透明但多一跳)→ Cluster(官方推荐)。

Cluster 核心:16384 slot 分片,CRC16 取模路由,Gossip 去中心化通信。

路由机制:正常直连、MOVED 永久迁移、ASK 临时迁移、Hash Tag 强制同 slot。

选型:新项目用 Cluster,旧项目维持 Codis,小规模不用分片。

总结

Redis 数据分片是将数据分散到多个节点以突破单机瓶颈的技术,有客户端分片、代理分片(Twemproxy/Codis)和服务端分片(Redis Cluster)三种方式。生产环境推荐 Redis Cluster,通过 16384 个 Hash Slot 实现自动分片、路由和故障转移。核心路由机制是 CRC16(key) % 16384,配合 MOVED/ASK 重定向和 Hash Tag 解决跨节点操作问题。