生产环境必须用 redis,file 和 array 驱动仅适用于开发或测试;cache_driver=redis 不生效常因 config/cache.php 中 'default' 未正确读取环境变量,需确认 config:cache 已刷新、连接配置隔离(如专用 cache 数据库)、并用 tinker 验证驱动实际值。

生产环境必须用 Redis,别碰 file 或 array 驱动——它们不是缓存,是障眼法。 本地开发可以临时用 file,但只要上测试或预发,就得切 Redis;否则你写的 Cache::remember() 在并发下会丢数据、不刷新、返回 null 还以为逻辑错了。
CACHE_DRIVER=redis 为什么总不生效
最常见原因是:.env 里写了 CACHE_DRIVER=redis,但 config/cache.php 中 'default' 还是 'file',Laravel 优先读这个配置,CACHE_DRIVER 只在该值为空时才兜底。
- 检查
config/cache.php文件顶部的'default' => env('CACHE_DRIVER', 'file'),确保env('CACHE_DRIVER')真的被加载(php artisan config:clear && php artisan config:cache后再试) - 运行
php artisan tinker --execute="echo config('cache.default');",输出不是redis就说明驱动根本没切过去 - Redis 连接失败时 Laravel 很少报错,
Cache::get()默认静默返回null,先用redis-cli -h ${REDIS_HOST} -p ${REDIS_PORT} ping确认服务可达
Redis 连接配错导致 Cache::get() 一直返回 null
不是代码问题,是连接参数错位。Laravel 的 Redis 缓存默认复用 config/database.php 里的 redis.default 连接,但很多人只改了 .env 的 REDIS_HOST,忘了 config/database.php 里 'default' 连接的 'database' 值是否冲突(比如 session 也在用 DB 0)。
- 在
config/database.php的redis.connections下新增专用连接,例如'cache' => [ 'host' => env('REDIS_HOST'), 'port' => env('REDIS_PORT'), 'password' => env('REDIS_PASSWORD'), 'database' => env('REDIS_CACHE_DB', 1) ] - 在
config/cache.php的stores.redis.connection改成'cache' - .env 补上
REDIS_CACHE_DB=1,避免和 session(DB 0)或 queue(DB 2)混用
php artisan cache:clear 清不掉缓存?
命令默认只清当前 store 下 Laravel 自己打前缀的键(如 laravel_cache:xxx),如果你手动调过 Redis::set()、用了 Cache::store('xxx')、或者开了 tags 缓存,它一概不管。
- 确认当前 store:执行
php artisan tinker --execute="echo config('cache.store');" - 清自定义 store:加
--store=redis参数,例如php artisan cache:clear --store=redis - 清 tagged 缓存:必须用
php artisan cache:clear --tags=users(仅 redis / database 驱动支持) - 彻底清 Redis 当前库:进
redis-cli执行FLUSHDB,但别在生产乱跑
Cache::remember() 缓存穿透怎么防
它默认把 null 也缓存进去,查不到就卡死一小时。这不是 bug,是设计如此——你得自己控制空值写入逻辑。
- 别这么写:
Cache::remember('user:123', 3600, fn() => User::find(123))(查不到就存null) - 改成显式判断:
$user = User::find(123); if (!$user) { Cache::put('user:123:miss', true, 60); return null; } Cache::put('user:123', $user, 3600); return $user; - 读取时先查
user:123:miss标记,存在就跳过 DB 查询,避免反复穿透 - 键名带业务前缀(如
user:)+ 统一 TTL,方便后期用redis-cli keys "user:*"批量定位
缓存失效时间不准、键名拼错、多 store 混用、空值误存——这些问题不会报错,只会让你花半天查“为什么数据明明更新了,页面还是旧的”。动手前先确认驱动真连上了,再看键有没有被其他地方悄悄覆盖,最后盯住服务器时间同步。Redis 不是开关一开就加速,是每个环节都得对得上。











