生产环境必须用 redis 或 memcached 驱动,file 驱动因锁文件、无原子操作、性能差而仅适用于本地开发;需确认 .env 中 cache_driver=redis、安装 phpredis 扩展,并正确配置 redis 连接参数。

缓存驱动选什么?redis 和 file 的实际差别
本地开发用 file 驱动最省事,但别在生产环境还这么干——它锁文件、慢、不支持原子操作,高并发下容易丢数据。生产必须切到 redis 或 memcached。laravel 默认配置里 REDIS_HOST 是 127.0.0.1,但很多新手没改 .env 里的 CACHE_DRIVER=redis,结果代码里调 Cache::get() 一直返回 NULL,还以为是代码写错了。
- 确认
.env中已设CACHE_DRIVER=redis(不是redis拼错,也不是漏了) -
redis驱动要求 PHP 装了phpredis扩展(不是predis),用php -m | grep redis检查 - 如果 Redis 服务不在本地,务必同步更新
REDIS_HOST、REDIS_PORT、REDIS_PASSWORD
Cache::remember() 怎么避免缓存穿透和空值误存
直接用 Cache::remember('key', 3600, fn() => $db->find($id)) 很方便,但如果数据库查不到记录,闭包返回 null,这个 null 也会被缓存一小时——下次请求还是穿透到 DB,但你以为缓存生效了。这不是 Laravel 的 bug,是设计如此。
- 手动判断结果是否为空,用
Cache::has()+Cache::put()控制写入逻辑 - 对可能为空的查询,统一存一个占位值,比如
Cache::put('user_123', '__NOT_FOUND__', 300),读取时检查是否等于该字符串 -
remember()的第二个参数是秒数,别传0或负数,Laravel 会当成永久缓存,Redis 里就再也删不掉了
php artisan cache:clear 清不掉某些缓存?
执行命令后 Cache::get('xxx') 还能取到值,大概率是因为你用了 tag 缓存(比如 Cache::tags(['users'])->put('profile_1', $data, 3600))。默认的 cache:clear 只清默认 store,不碰 tagged cache。
- 清 tagged 缓存得用
php artisan cache:clear --tags=users - 注意:只有
redis和database驱动支持 tags,file和Array驱动下tags()调用会静默失败 - 线上执行前先
php artisan tinker里试一下Cache::tags(['test'])->get('x')是否真有内容,避免误判
缓存键名带变量时,为什么总冲突或取不到?
写成 Cache::get('user_'.$id.'_profile') 看似合理,但一旦 $id 是字符串(比如 'admin')或含特殊字符(如 'user-123'),Redis 键名就可能非法或与其他键混淆。更隐蔽的问题是,不同环境(本地/测试/生产)用了不同 cache prefix,导致键名实际是 production:user_123_profile,但你调试时只搜 user_123_profile。
- 用
Cache::store()->getPrefix()查当前前缀,拼键时显式加上 - 推荐用
Str::slug()或md5()处理动态部分,比如'user_'.md5($id).'_profile' - 别在键里塞 json 字符串或数组,序列化后不可读、难调试,也容易超长(Redis 单 key 最大 512MB,但业务上超过 1KB 就该警惕)
缓存最难的从来不是配通,而是键怎么命名、空值怎么处理、tag 在哪用、prefix 怎么对齐——这些细节不盯住,上线后问题都是零散又难复现的。