深蓝黑背景品牌封面:底部栏式标题区,主标题「Redis 分片有哪几条路」,副标题「客户端、代理、集群怎么选」;上半部分原创装饰——左中右三根立柱并排,柱顶各悬一枚图标:直连箭头、方形代理盒、三圆点集群网,寓意三条水平扩展路线;左下标注「经典题解析 · 缓存」,右下标注「Day 06 · 10-14」 图 1:本文封面,三根立柱就是三条分片路线。

先说明属性:这是一篇经典题解析,题目出自本地历史面试资料,与任何公司的当前招聘无关。单机 Redis 装不下、扛不住之后怎么办,是缓存方向绕不开的系统设计题;面试官想听的不是某条路的细节背诵,而是你能不能把三条路的取舍摆上同一张桌子。

想象面试现场:「Redis 数据量超过单机内存了,怎么水平扩展?客户端分片、代理分片、官方集群各有什么取舍?」

先把问题说清楚:分片解决什么。

分片(sharding)是把整个数据集拆到多个 Redis 实例上,每个实例只持有键的一个子集。它同时解两个瓶颈:容量——内存不再受单机限制;吞吐——读写压力摊到多台机器。代价也随之而来:路由谁来算、扩容时数据怎么搬、多键操作还能不能做。三条路线的分野,全在这三个代价由谁承担。

路线一:客户端分片。

路由逻辑写在客户端里:按键的哈希规则(取模或一致性哈希)直接选出目标节点,业务代码连哪个实例自己说了算。优点是零额外组件、少一跳、延迟最低。代价是节点变化难平滑:加一台机器,取模规则下大量键的归属全变,要么改客户端发布、要么忍受大规模数据迁移,扩容是个项目而不是一个操作。适合实例拓扑长期稳定、追求简单的小规模场景。

路线二:代理分片。

在客户端和 Redis 之间加一层代理,请求先落到代理,由代理按统一规则路由转发,客户端看到的是「一个逻辑 Redis」。优点是客户端无感知、路由规则集中管理,存量业务几乎不用改。代价同样明确:多一跳网络延迟;代理层自身成了新的可用性责任方,要部署多副本、要做监控,运维对象从「几个 Redis」变成「几个 Redis 加一组代理」。

路线三:官方集群(Redis Cluster)。

节点自治的去中心化方案:全部键空间被划分为 16384 个哈希槽,键的归属槽位由 CRC16 对 16384 取模算出,每个主节点负责一段槽位;槽位可以在节点间在线迁移,扩缩容和故障转移都是内置能力——部分节点失联时集群照常服务,多数主节点不可用才整体不可用。代价是使用约束:多键操作、事务、Lua 脚本里涉及的键必须在同一个槽位,跨槽多键操作直接不被支持——官方给的解法是哈希标签(hash tag),键里花括号包住的子串相同时保证落在同一槽位,可以把需要一起操作的键人工钉在一起。协议变复杂了,客户端必须是集群感知的。

对比图:三列并排。左列客户端分片——客户端按哈希规则直接选节点,优点是零额外组件、延迟低,代价是扩容要改客户端并迁移数据,节点变化难平滑。中列代理分片——请求先落到代理层再由其路由,优点是客户端无感知、路由集中管理,代价是多一跳延迟且代理自身要保高可用。右列官方集群——节点间自治分槽,优点是在线扩缩容与故障转移内置,代价是协议变复杂、多键与跨槽操作受限。底部结论:要简单选客户端、要对存量无侵入选代理、要长期弹性选官方集群;选定型先看团队运维能力,再看数据规模 图 2:三条路线的取舍对比与选型结论。

选型框架与可能的追问。

一句话结论:要简单选客户端、要对存量无侵入选代理、要长期弹性选官方集群。先评估团队的运维能力,再评估数据规模的增长预期——方案不是越先进越好,是越匹配越好。「三条路能混用吗?」能,客户端路由到代理、代理后面再接集群的过渡形态在真实系统里存在,但每叠一层就多一层的延迟与故障面。「Cluster 的多键限制怎么绕?」哈希标签之外,就是把多键逻辑拆回单键、把聚合挪到应用层——这是选择集群方案时要在数据模型设计阶段就想清楚的事,而不是上线后再补。易错点有二:一是把分片当纯运维问题,数据模型不改,多键操作上线即报错;二是只看容量不看迁移成本,选了一条扩容要全量搬数据的路,第二次扩容时痛不欲生。

回到面试现场,建议的答题节奏:先定义分片解决的两个瓶颈,再按「路由谁来算」把三条路并排讲清各自优缺点,然后给出选型框架,最后主动提集群的多键限制与哈希标签——这个细节是区分「背过方案名」和「真用过」的分水岭。AI 平台缓存层扩容时面对的正是同一张决策表:客户端路由、代理层、官方集群,运维复杂度与迁移成本都在这张表里。

你们团队的缓存层现在走在哪条路上,踩过什么坑?欢迎聊聊。