缓存击穿指热点key过期时并发请求穿透查库,laravel 11通过redis分布式锁(cache::lock)、空值缓存+随机ttl、热点数据预热及原子命令驱动四措并举解决。

在 Laravel 11 中,缓存击穿特指某个高热度数据(如商品详情、用户主页、热门文章)的缓存 key 刚好过期,而此时大量并发请求同时涌入,全部穿透到数据库查询并尝试重建缓存,导致 DB 瞬时压力飙升甚至超时。这不是配置错误,而是高并发场景下的典型竞争问题。解决核心是:**不让多个请求同时查库+写缓存**。
用分布式锁控制缓存重建入口
这是 Laravel 11 最直接、最可控的方案。利用 Redis 驱动原生支持的原子锁机制,在缓存未命中时抢占“重建资格”:
- 调用 Cache::lock('cache:product:123', 10) 获取一把 10 秒有效期的锁,key 与业务数据强关联
- 获取成功 → 立即查数据库 → 写入缓存(如 Cache::put('product:123', $data, 3600))→ 主动释放锁
- 获取失败 → 不查库,而是短暂休眠(如 usleep(50000))后重试 Cache::get(),大概率此时缓存已被其他请求写入
空值缓存 + 随机 TTL 防止反复穿透
对可能为空的结果也做缓存,配合时间扰动,从源头降低击穿概率:
- 当数据库查不到记录(如 Product::find(9999) 返回 null),仍执行 Cache::put('product:9999', null, 120 + rand(0, 300))
- 随机加 0–5 分钟,避免大量空值在同一秒过期,形成“空值雪崩”
- 业务层读取时统一判断:if (is_null($cached = Cache::get('product:123'))) { return response()->notFound(); }
预热关键热点数据,避开过期高峰
Laravel 11 支持在部署或低峰期主动加载高频 key,让缓存始终处于“活跃状态”:
- 写一个 Artisan 命令(如 php artisan cache:warm-product),批量查询 TOP 100 商品并写入缓存,TTL 设为比默认长 10%
- 结合 Schedule 每小时刷新一次,或监听模型事件(如 ProductUpdated)自动触发局部预热
- 避免所有 key 使用同一固定 TTL;对核心数据采用 Cache::rememberForever() + 手动失效(如更新时 Cache::forget('product:123'))
升级驱动并启用 Redis 原子命令保障
Laravel 11 默认使用 Predis 或 phpredis 作为 Redis 客户端,确保你启用了真正的原子操作:
- 确认 config/cache.php 中 redis 驱动的 connection 配置正确,且 Redis 服务支持 SETNX 和 EVAL
- 锁底层依赖 Redis::set($key, $val, ['NX', 'EX' => $ttl]),若返回 false 表示已被占用,无需额外判断
- 不推荐用 file 或 database 驱动处理高并发击穿场景——它们无法提供跨进程原子性











