做电商网站的时候,商品详情页往往是流量最集中的地方。每次用户点开一个商品,系统都要查数据库、拼接图片、读取规格参数,一来二去,服务器压力就上来了。这时候,缓存就成了必不可少的一环。
为什么详情页特别适合缓存
大多数商品的信息不会频繁变动,比如名称、描述、价格、图片这些内容,可能几天甚至几周才改一次。但访问量却可能每天成千上万。如果每个请求都走后端处理,纯属浪费资源。把渲染好的页面或数据缓存起来,能直接减少数据库查询和模板渲染的开销。
常见的缓存层级
一般会采用多层缓存策略。比如先看浏览器有没有缓存,没有再查 CDN,CDN 没有就打到反向代理(如 Nginx),最后才落到应用服务器。这样层层兜底,既能加快响应速度,又能降低源站压力。
比如在 Nginx 配置里加一段缓存规则:
location ~ /item/\d+ {
proxy_cache my_cache;
proxy_cache_valid 200 5m;
proxy_cache_key $uri;
proxy_pass http://backend;
}
这样,同一个商品链接在 5 分钟内被访问多次,只有第一次真正打到后端,后面的都从 Nginx 缓存返回。
动态数据怎么处理
也不是所有内容都能无脑缓存。比如库存数量、实时销量、用户是否已收藏,这些是动态的。常见做法是静态部分整体缓存,动态内容通过 Ajax 单独拉取。
页面加载时,先展示缓存的主体信息,再异步请求:
fetch('/api/item/status?itemId=12345')
.then(res => res.json())
.then(data => {
document.getElementById('stock').innerText = data.stock;
});
这样既享受了缓存的好处,又保证了关键信息的实时性。
缓存失效的时机
商品改价了,库存清零了,或者下架了,缓存就得及时清理。不能让用户看到过期信息。通常在管理后台修改商品后,主动推送一个清除指令。
比如用 Redis 做缓存,可以这样操作:
DEL cache:item:12345
PUBLISH item_update_channel 12345
多个服务订阅这个频道,收到消息后同步删除本地缓存,保证一致性。
别忽视缓存穿透问题
有些恶意请求会不断查不存在的商品 ID,比如 /item/99999999,这种请求每次都会穿透到数据库。解决办法是用布隆过滤器提前拦截,或者对查不到的结果也缓存一个空值,设短一点的过期时间,比如 30 秒。
比如在代码里加上一层判断:
if (redis.get('cache:item:' + id) === null) {
if (redis.get('negative_cache:' + id)) {
return send404();
}
}
这样能有效防止数据库被无效请求拖垮。
缓存不是一劳永逸的工具,得结合业务节奏调整策略。大促前可以延长缓存时间,活动一结束立刻刷新。平时则保持灵活更新。用好了,用户体验和服务器负载都能轻松不少。