缓存需精准识别热点、控制失效节奏、避免污染,核心是承接20%高频查询。应归一化sql统计、排除动态/大结果查询,验证数据静态性;分层选用本地缓存、redis或数据库缓存;按主键/业务域精准失效,设二级过期机制;监控命中率等指标并持续优化。

读多写少场景下,缓存不是“加了就快”,而是要精准识别热点、控制失效节奏、避免缓存污染。核心在于让缓存真正承接住那20%高频查询,而不是被动兜底所有读请求。
识别真正的热点SQL与数据
不能只看“执行次数多”,得结合业务语义和访问模式判断是否值得缓存:
- 统计标准化SQL(如将 SELECT * FROM orders WHERE user_id = 123 和 user_id = 456 归一为 SELECT * FROM orders WHERE user_id = ?),用 pg_stat_statements(PostgreSQL)或慢查日志+解析工具(MySQL)提取Top 20高频模板
- 排除明显不适合缓存的SQL:含 NOW()、RAND()、用户会话变量、或结果集超2MB的聚合查询
- 验证数据静态性:对命中率高的SQL,检查其涉及表的 UPDATE/DELETE QPS —— 若某配置表每天仅更新1次,但该SQL每秒执行500次,就是理想缓存目标
选对缓存层级与策略
不同场景适用不同缓存位置,优先级从近应用到近数据:
- 应用层本地缓存(如Caffeine):适合用户维度强隔离的数据,例如“用户个人资料”“设备绑定信息”,TTL设为分钟级,避免跨实例不一致
- Redis集中缓存:用于共享型热点,如商品基础信息、活动开关、城市列表;键设计建议为 table:primary_key(如 product:10086),值存完整行JSON或关键字段哈希
- 数据库原生缓存(如MySQL 5.7 query_cache):仅限极静态小表,且必须满足 命中率>70% 才启用;MySQL 8.0+已移除,不可依赖
控制缓存一致性与失效粒度
缓存失效是最大风险点,粗放清空=雪崩,精准失效=可控:
- 禁止“清空全部缓存”操作;改用“按主键/业务域失效”,例如更新商品价格后,只删 product:10086 和 category:shoes 两个键
- 对关联数据做缓存穿透防护:如订单详情页需查用户信息,可将 order_id → user_id 映射也缓存,并监听用户表变更异步刷新
- 设置二级过期机制:主缓存TTL设为业务容忍上限(如30分钟),再加一个“逻辑过期时间”字段存于value内,后台线程定期扫描并异步重建即将过期的热点项
监控与迭代闭环
缓存效果必须可量化,否则很快退化为技术债:
- 关键指标监控:缓存命中率(目标>85%)、平均响应时间下降幅度、后端DB的 Com_select 下降比例
- 自动识别失效热点:当某缓存key连续5分钟未被访问,自动归档;当某SQL缓存命中率突降至<50%,触发告警并检查对应表是否开始频繁更新
- 每月Review缓存键分布:用Redis SCAN 抽样分析key前缀占比,若发现 order_* 占比超60%但命中率仅40%,说明订单类缓存设计不合理,需转向更细粒度(如只缓存订单状态摘要)










