Redis 缓存 Key 应该如何设计?前缀、版本号和长度怎么取舍?
简化版
Redis Key 设计要做到可读、唯一、可治理、不过长。常见格式是“业务前缀:对象类型:版本:标识”,例如 mall:user:v2:1001。前缀便于隔离和扫描,版本号便于兼容升级,但 key 过长会增加内存成本。
详细版
好的 key 不是随便拼字符串。它要避免冲突,便于定位业务归属,支持批量治理,同时不能把太多冗余信息塞进 key 名。
常见原则包括:统一分隔符、固定命名规范、包含业务域和对象类型、必要时加版本号、避免用户输入直接成为 key、控制长度、不要用 KEYS 做批量操作。
对于 Redis Cluster,还要理解 hash tag:{user:1001}:profile 和 {user:1001}:timeline 会落到同一槽,方便少量多 key 操作,但滥用会造成槽位倾斜。
完整版教学
一、Key 设计为什么重要
Redis key 是数据入口,也是运维入口。线上排查时,看到 u:1、cache_abc 很难判断业务来源;看到 mall:user:v2:1001 就能快速定位到商城用户缓存。
key 设计差会带来三个问题:冲突、难治理、成本高。冲突会覆盖数据;难治理会导致迁移和清理困难;成本高来自 key 名本身也占内存。
所以 key 规范是 Redis 工程质量的一部分,不是命名审美。
二、推荐的命名结构
常见格式可以是:
业务域:对象类型:版本:业务ID[:字段]
mall:user:v2:1001
mall:goods:v1:8899:price
pay:order:v3:202607300001
业务域解决归属,对象类型解决语义,版本号解决结构升级,业务 ID 保证定位。分隔符建议统一用冒号,方便人工阅读和工具解析。
三、版本号有什么用
缓存 value 结构变化时,旧 key 里的数据可能不能被新代码正确解析。加入版本号后,新旧版本可以并存,新代码读 v2,旧代码读 v1,灰度更安全。
例如用户缓存从纯昵称变成 JSON 对象:
user:v1:1001 = "Tom"
user:v2:1001 = {"name":"Tom","level":3}
代价是短期内内存翻倍一部分,所以要有旧版本清理计划。
四、Key 长度和内存成本怎么权衡
key 名越清晰通常越长,但 Redis 会为每个 key 存储字符串。海量 key 下,长度差异会被放大。
假设 5000 万个 key,每个 key 多 20 字节,裸 key 名就多约 1GB,还不算 allocator 对齐和元数据。可读性和成本要平衡。
| 设计 | 优点 | 问题 |
|---|---|---|
mall:user:v2:1001 | 可读、可治理 | 略长 |
u:1001 | 省内存 | 语义差、易冲突 |
user-profile-cache-production-v2-1001 | 很清楚 | 过长 |
五、Cluster hash tag 要谨慎
Redis Cluster 按 key hash 到槽位。hash tag 可以指定参与计算的部分,例如 {user:1001}:profile 和 {user:1001}:setting 会落到同一个槽。
这对少量多 key 操作有用,但如果所有热点都写成 {global}:xxx,就会把大量 key 压到同一槽,造成节点倾斜。
因此 hash tag 只用于确实需要同槽的相关 key,并且 tag 要有足够分散度。
六、常见误区与追问
- 误区:Key 只要不重复就行。 还要可读、可治理、可迁移、可监控。
- 误区:Key 越短越好。 过短会丢失语义,排查和清理成本变高。
- 误区:版本号没必要。 缓存结构升级、灰度发布和回滚时版本号很有价值。
- 追问:能不能用用户输入直接拼 key? 要做规范化和长度控制,避免特殊字符、超长 key 和注入式污染。
- 追问:hash tag 为什么不能滥用? 它会影响槽位分布,错误 tag 可能造成热点槽。
七、加强记忆
记忆钩子:Redis Key 是缓存世界的门牌号;门牌要看得懂、找得到、搬家方便,但不能长到比房子还占地方。
回答这题按“命名结构、版本升级、长度成本、Cluster hash tag、治理规范”展开。能讲出 key 名也占内存、hash tag 会倾斜,就很有工程味。