缓存Key设计的"七要七不要"
一、命中率篇(怎么让缓存有效)
-
要分层级,不要平铺直叙
- 口诀: 项目:模块:功能:ID
- 示例:
taobao:item:detail:123优于item123 - 理由: 便于管理统计,避免不同业务Key冲突。
-
要固定参数顺序,不要直接拼接
- 口诀: 先排序,再哈希
- 示例: 查询参数先按字母排序(a=1&b=2),然后MD5作为Key。
- 理由: 解决
?a=1&b=2和?b=2&a=1生成两个不同Key的问题,提升复用率。
-
要嵌入版本号,不要原地修改
- 口诀: 旧数据让它静默过期
- 示例: 升级数据结构时,写入
user:v2:123,旧user:v1:123自然失效。 - 理由: 防止代码升级后读取旧缓存导致反序列化报错。
-
要区分动静数据,不要混为一谈
- 口诀: 高频变和低频改要分开
- 示例: 商品详情(缓存久)和商品库存(不缓存或极短缓存)分开存。
- 理由: 避免修改频繁的字段导致整个大缓存频繁失效。
二、安全性篇(怎么防止出事故)
-
要脱敏处理,不要明文暴露
- 口诀: 手机号、身份证号必须哈希
- 示例:
index:phone:md5(13800138000)而不是phone:13800138000。 - 理由: 防止日志泄露用户隐私,防止Redis被入侵后直接拖走明文敏感数据。
-
要控制长度,不要大而不当
- 口诀: Key名要精简,百字节以内
- 示例: 能用
user:123:avatar就不用user_profile_image_12345_2024_version_3。 - 理由: 过长的Key占用内存,降低查询效率,易被利用进行内存攻击。
-
要防止穿透,不要有"万能Key"
- 口诀: 对非法ID也要缓存空值
- 示例: 查询
item:-1,数据库没有,缓存一个item:-1=null并设置短过期。 - 理由: 防止恶意使用不存在的ID频繁穿透数据库。
经典示例对比
| 维度 | 反面教材(踩坑) | 正面案例(推荐) |
|---|---|---|
| 用户信息 | user_123456 |
user:info:v3:123456 |
| 搜索列表 | 手机_1_20 |
search:md5(k=手机&p=1&s=20) |
| 手机索引 | phone:13800138000 |
phone:index:5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8 |
| 文章详情 | article_9527 |
blog:article:v2:9527 |
总结一句话:
Key的设计要像家庭地址------既要有清晰的层级(国家/省份/城市/街道)保证能找到(命中率),又不能把银行卡密码写在门牌号上(安全性)。v