什么是缓存策略设计模式
在开发网站或应用时,经常会遇到用户频繁访问相同数据的情况。比如一个电商首页的商品列表,每天被成千上万的人查看,如果每次请求都去数据库查一遍,服务器很快就会扛不住。这时候,缓存就派上用场了。
缓存策略设计模式,不是某个具体的代码框架,而是一套解决“什么时候读缓存、什么时候更新缓存、缓存失效怎么处理”等问题的方法论。它帮助开发者在性能、一致性、复杂度之间找到平衡点。
常见的缓存策略模式
最常用的几种策略有:Cache-Aside、Read/Write Through、Write Behind 和 TTL 管理方式。每种都有适用场景。
Cache-Aside 模式:最接地气的做法
这是目前使用最广泛的模式。简单说就是:读数据时先查缓存,没有就从数据库加载,并写入缓存;写数据时,先更新数据库,再删除缓存。
比如你在刷短视频,每次滑到同一个热门视频时,内容几乎立刻出现,就是因为它的信息已经被缓存了。只有当作者修改了标题或封面,系统才会把旧缓存删掉,下次访问重新加载。
// 伪代码示例:Cache-Aside 读操作
function getData(id) {
data = redis.get("video:" + id);
if (data == null) {
data = db.query("SELECT * FROM videos WHERE id = ?", id);
redis.setex("video:" + id, 3600, data); // 缓存1小时
}
return data;
}
// 写操作:更新数据库后清除缓存
function updateData(id, newData) {
db.update("UPDATE videos SET title = ? WHERE id = ?", newData.title, id);
redis.del("video:" + id);
}这种做法实现简单,对现有系统侵入小,适合大多数业务场景。
Read/Write Through:由缓存层接管数据操作
在这个模式里,应用不再直接操作数据库,而是通过一个“缓存层”来统一处理读写。缓存服务自己负责和数据库同步。
比如你用某个会员系统查询用户积分,系统不关心数据在哪,只问缓存要。如果缓存里没有,它自动去数据库取并保存;更新时也只通知缓存,由缓存去更新数据库。
这种方式让业务逻辑更干净,但要求缓存系统足够可靠,且能处理数据库交互逻辑。
Write Behind:异步写入提升性能
这个模式像是“先记本子再登账”。数据先写进缓存,立即返回成功,后台线程慢慢把变更同步到数据库。
适用于写操作频繁但允许短暂延迟的场景,比如记录用户浏览行为、日志统计。优点是响应快,缺点是如果缓存宕机,可能丢数据,所以必须配合持久化机制。
如何设置过期时间
缓存不能永久存在。新闻热点过了三天没人看了,缓存还留着只会浪费内存。TTL(Time to Live)机制就是给缓存设个“保质期”。
静态内容如城市列表可以缓存几小时,用户登录状态可能只缓存30分钟。有些系统还会结合懒加载,在缓存快到期时提前刷新,避免冷启动卡顿。
实际项目中,经常混合使用多种策略。比如商品详情页用 Cache-Aside,购物车数据用 Write Behind,用户配置用 Read Through。
别忽视缓存击穿和雪崩
当大量请求同时访问一个刚过期的热点数据,就会触发“缓存击穿”,瞬间压垮数据库。可以用互斥锁控制重建缓存的次数,或者让部分请求继续使用旧缓存直到新数据加载完成。
“缓存雪崩”则是大面积缓存同时失效,整个系统直接裸奔。解决方案包括错峰设置TTL、使用二级缓存、开启热点自动探测和常驻机制。
缓存策略的设计,本质上是在做权衡。不是越快越好,也不是越久越好。关键是要理解业务特点:哪些数据变化少?哪些容忍延迟?哪些绝对不能出错?想清楚这些,才能选出最适合的模式。