You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 8 Redis缓存仅在Tinker执行查询时生效问题排查

问题根因

你的Redis缓存未生效、请求耗时过高是三处代码逻辑错误共同导致的,和Redis服务配置无关:

  • 路由模型绑定提前触发无缓存数据库查询:控制器方法签名声明了Application $application参数时,Laravel会在执行方法体内的缓存逻辑前,自动根据路由参数从MongoDB查询对应模型实例,这个过程完全不经过Redis缓存,每次请求都会先执行一次数据库查询。你观察到的「Tinker中提前执行find查询后请求变快」现象,本质是MongoDB将查询过的文档、索引加载到了内存工作集,后续相同查询直接走内存不需要扫磁盘,并非Redis缓存命中导致。
  • 缓存键生成规则不稳定,无法命中存量缓存:你直接将$application模型实例插值到字符串作为缓存键,MongoDB模型的主键默认是ObjectId类型,直接将实例转字符串时,若模型未完成全属性初始化,会混入对象内存标识、动态属性值,导致每次请求生成的缓存键都不重复,Redis中会存入大量永远不会被二次访问的无效键,每次请求都会走到闭包内的慢查询逻辑。
  • 闭包内查询逻辑错误,触发额外全表扫描:你编写的Application::with([...])->find($application)->first()存在严重逻辑缺陷:
    • find()方法预期接收主键值作为参数,传入整个模型实例时,MongoDB查询构造器会遍历模型所有属性生成多条件匹配规则,额外增加查询开销
    • find()本身执行后已经返回单条模型实例,后续链式调用first()会在该实例上触发全新的查询,等同于执行无筛选条件的Application::first(),在1000万行数据的集合中,这个无索引全表扫描操作会直接带来数秒的耗时。
修复方案

调整后的可正常运行代码如下:

/**
 * Display the specified resource.
 *
 * @param  string  $application  直接接收路由传入的主键ID,避免提前触发无缓存模型查询
 * @return \Illuminate\Http\Response
 */
public function show($application)
{
    // 使用稳定的字符串主键生成固定缓存键,避免键名动态变化
    $applicationData = Cache::store('redis')->remember("application:{$application}", Carbon::now()->addMinutes(30), function () use ($application) {
        // 直接传入主键ID执行查询,移除多余的first()调用,保留关联预加载逻辑
        return Application::with([
            'payday', 'response', 'apiLinks'
        ])->find($application);
    });

    return response()->json([
        'application' => $applicationData
    ], 200);
}

如果需要保留路由模型绑定的使用体验,可以自定义路由模型绑定的解析逻辑,让模型解析过程优先读取Redis缓存,避免每次请求直接穿透到MongoDB。

内容的提问来源于stack exchange,提问作者Ryan H

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 01:03:17