Laravel 10 中 Eloquent 缓存需协同时机、键名、失效与查询结构:优先用 remember() 封装高频读取,结合作用域、缓存标签及事件驱动失效,避免全表缓存,推荐查询粒度缓存与 Rennokki\QueryCache。

在 Laravel 10 中,把数据库缓存和 Eloquent 结合好,不是加个 remember() 就完事——关键在于缓存时机、键名设计、失效控制与查询结构的协同。用对了,QPS 上升、DB 压力下降;用错了,数据陈旧、键冲突、缓存击穿全来。
优先用 remember() 封装高频读取查询
对状态类、配置类、列表页等读多写少的数据,直接在 Eloquent 链式调用中插入 remember(秒数) 最轻量高效:
-
User::where('role', 'admin')->remember(3600)->get()—— 缓存一小时,避免重复查管理员列表 -
Post::with('author', 'category')->published()->latest()->remember(1800)->paginate(12)—— 预加载 + 作用域 + 缓存三合一,分页结果直上缓存 - 缓存键默认由模型类名、查询 SQL 哈希及绑定参数生成,无需手动拼接,但若需精准清理,可显式传入键名:
->remember(7200, 'homepage_posts')
配合模型作用域自动带缓存逻辑
把 remember() 内聚进作用域里,让业务调用更干净:
- 在模型中定义作用域时嵌入缓存:
{
return $query->where('view_count', '>', 1000)->remember(3600);
}
- 调用时保持链式习惯:
Post::popular()->latest()->get(),缓存自动生效 - 多个作用域组合时,
remember()只需出现在任一位置(推荐放在最外层或首个条件后),避免重复设置
缓存失效必须与模型生命周期对齐
缓存不清理,数据就 stale。Laravel 不会自动感知你手写的 SQL 或批量更新,所以得靠事件驱动:
- 使用
cacheable扩展包(genealabs/laravel-model-caching)可全自动监听saved/deleted/restored事件,清除该模型所有相关缓存项 - 若手动管理,可在模型的
booted中注册监听器:
{
static::updated(fn ($model) => Cache::forget("post:{$model->id}"));
static::created(fn ($model) => Cache::forget('posts:all'));
static::deleted(fn ($model) => [
Cache::forget("post:{$model->id}"),
Cache::forget('posts:all')
]);
}
- 对集合级缓存(如
Post::all()),建议用缓存标签(Cache::tags(['posts'])->remember(...))统一管理,支持按标签批量清除
慎用全量缓存,优先选查询粒度缓存
全表缓存(如 Post::all())看似省事,但极易引发一致性问题和内存膨胀:
- 推荐改用
Rennokki\QueryCache:它按每个查询构建器实例生成唯一键,Post::where('status', 1)->get()和Post::where('status', 0)->get()缓存互不干扰 - 设置模型级默认 TTL:
protected $cacheFor = 120;,再配合->cacheFor(300)覆盖特定查询,灵活可控 - 避免缓存含未序列化资源的对象(如 Closure、PDO 实例),Eloquent 模型本身可安全缓存,但记得排除
$appends中动态计算字段,或重写toArray()控制输出


















