我把91网的缓存管理拆给你看:其实一点都不玄学(建议反复看)

开门见山:缓存不是黑盒魔法,而是一套工程策略的组合。把对的策略放在对的层级、用对的失效与一致性手段,就能把流量浪尖驯服、把后端压力降到可控范围。下面把一个典型互联网产品(以“91网”为例)的缓存管理拆解成可落地的模块、原则与操作步骤,便于直接在生产环境里复用和验证。
一、缓存分层与角色划分
- CDN(边缘缓存):静态资源、图片、视频分发优先。支持Cache-Control、Surrogate-Key、Purge API。
- 反向代理 / 边缘应用层(如Nginx + Varnish / Fastly):页面缓存、SSR缓存、路由级别缓存。
- 应用内缓存(本地进程缓存):热点配置、RPC结果,极低延迟读取。
- 分布式内存缓存(Redis / Memcached):会话、数据库查询结果、复杂聚合的缓存层。
- 数据库缓存(物化视图、二级索引缓存):写频低、读频高的数据预计算。
二、缓存键设计(决定命中率)
- 使用结构化、可读的键:service:resource:id:version:flags 示例:article:details:12345:v2
- 把影响结果的因素都纳入键:用户分片、语言、设备、AB测试桶、查询参数(必要时用hash)。
- 切忌把高基数(如用户ID)直接用作顶层静态缓存键,避免key爆炸。
三、失效策略与一致性模式
- TTL + 主动失效:为大多数资源设置合理TTL(分钟到小时),通过API触发Purge/Invalidate进行即时更新。
- Tag/Surrogate-Key:对CDN或代理使用tag,更新时按tag批量作废,避免逐条清理。
- 写时失效(Write-through / Write-back)
- Write-through:更新时同时写缓存(适合强一致性需求,但写延迟上升)。
- Cache-aside(常用):读先查缓存未命中则读DB并回填缓存;写后删除/更新缓存。
- 弱一致场景用stale-while-revalidate:返回旧值同时后台异步刷新,提升响应并降低回源压力。
四、避免缓存雪崩/击穿/穿透
- 缓存穿透:对不存在的key频繁打穿,采用布隆过滤器或对空结果缓存一个短TTL。
- 缓存击穿:热点Key在过期瞬间大量并发回源,采用互斥锁(mutex)、singleflight(Go)或请求合并。
- 缓存雪崩:大量Key同一时间失效,采用随机TTL抖动(TTL += rand(0, jitter))或分散失效窗口。
五、HTTP缓存与CDN实践(页面/资源)
- 常用Header:
- Cache-Control: public, max-age=3600, stale-while-revalidate=30, stale-if-error=86400
- ETag / Last-Modified:配合条件请求减少全量回传
- Vary: Accept-Encoding, User-Agent(慎用:会增加缓存分片)
- 静态资源采用文件名指纹(hash)实现长期cache(max-age=31536000),更新靠文件名改变。
- 动态页面用短TTL + 后台预热/边缘渲染结合。
六、监控与度量(没有数据就没有优化)
- 必备指标:命中率(hit ratio)、请求量、回源率、平均响应时间、p95/p99、缓存容量、eviction rate、空结果率。
- 设置告警:命中率骤降、回源延迟上升、Redis慢命令或内存溢出。
- 定期分析Top Miss Keys与Top Hot Keys,作为调整策略依据。
七、运维与演练
- 提供安全的Purge/Invalidate API,记录审核日志,避免误删。
- 预演失效场景:在非高峰期演练批量清理、单点缓存失效恢复流程。
- 灾难恢复:Redis持久化(AOF/RDB)与主从复制,做好备份及故障切换策略。
八、典型代码/配置要点(伪代码示例)
-
Cache-aside 读流程: value = cache.get(key) if value != nil: return value lock = acquirelock(key) // 防止击穿 if lock acquired: value = db.query(key) cache.set(key, value, ttl) releaselock(key) return value else: wait for cache to be filled or return fallback
-
HTTP 示例Header: Cache-Control: public, max-age=60, stale-while-revalidate=30 ETag: "v2-abcdef123456"
九、常见误区(踩雷提醒)
- 把所有东西都缓存:敏感/私有数据、强一致性场景需慎重。
- 盲目追求极高TTL:会导致数据陈旧或更新复杂化。
- 不监控就不动手:没有监控就没有发现热点与回源瓶颈。
十、实践路线图(从0到1到规模化) 1) 基线收集:部署必要监控,统计当前命中率与热点API。 2) 分层缓存规划:确定哪些资源走CDN、哪些走Redis、哪些只需本地缓存。 3) 小步迭代:先对最热的top 10资源上缓存,观察指标。 4) 增强一致性:实现tag/purge,并为关键写操作设计失效流程。 5) 防护与优化:引入布隆过滤、请求合并、TTL抖动。 6) 自动化与文档:把缓存策略写成部署文档与运维Runbook。
结语 把91网的缓存拆开看,其实就是把几个简单的原则在多个层面上协调起来:合适的分层、严谨的键设计、稳健的失效策略、以及完整的监控和演练。把这些环节做细、做透,缓存就不再玄学,而是能稳定放大系统承载力的武器。建议先把上文的“实践路线图”跑一遍,遇到具体问题随时拿来细聊。