Laravel默认不启用Redis缓存,必须安装phpredis扩展、配置.env(CACHE_DRIVER=redis等)、修改config/cache.php的default为redis、确认config/database.php中redis连接有效,否则Cache::get()仍走file驱动;推荐用Cache::remember()避免竞态,注意空值缓存与过期时间错峰防雪崩。

Laravel 默认不启用 Redis 缓存,必须手动改配置、装扩展、验证连接,否则 Cache::get() 仍走 file 驱动,完全没效果。
确认 Redis 扩展已安装且被 PHP 加载
不装 phpredis 扩展,Laravel 会自动回退到 predis(纯 PHP 实现),性能差、不支持管道和部分原子操作,线上环境不推荐。
- 运行
php -m | grep redis,看到redis表示扩展已加载 - 若无输出,需用
pecl install redis安装,并在php.ini中添加extension=redis.so(Linux/macOS)或extension=php_redis.dll(Windows) - 修改后重启 PHP-FPM 或 Apache,再执行
php --ri redis查看版本和配置项
修改 config/cache.php 和 .env 启用 Redis 驱动
只改 .env 不够,Laravel 7+ 起默认 cache.php 的 default 是 file,必须显式指向 redis。
-
.env中设置:CACHE_DRIVER=redis、REDIS_HOST=127.0.0.1、REDIS_PORT=6379(如密码非空,加REDIS_PASSWORD=xxx) -
config/cache.php中确保'default' => env('CACHE_DRIVER', 'redis'),且'stores'['redis']下的'connection'值与config/database.php中 Redis 连接名一致(默认是'default') - 别漏掉
config/database.php里redis数组是否已配好host/port—— Laravel 缓存底层实际调用的是这个连接
用 Cache::remember() 替代手写 if-else 读写逻辑
直接调 Cache::get() + Cache::put() 容易出竞态条件(cache miss 时多个请求同时查 DB 再写缓存),remember() 自动处理原子性。
- 错误写法:
$data = Cache::get('posts'); if (!$data) { $data = Post::all(); Cache::put('posts', $data, 3600); } - 正确写法:
$data = Cache::remember('posts', 3600, function () { return Post::all(); }); - 注意:闭包内不能用
$this,需用use ($var)显式传参;过期时间单位是秒,不是分钟 - 对模型集合,建议用
Cache::remember('posts.'.$id, ...)按 ID 分 key,避免单 key 过大拖慢 Redis
缓存穿透与雪崩必须主动防御
Laravel 缓存层本身不提供布隆过滤或互斥锁,高频场景下容易被击穿或集体过期导致 DB 崩溃。
- 空值缓存:查不到数据时,
Cache::put('post.9999', null, 60)存个短时效空值,防止反复穿透 - 随机过期时间:不要所有 key 都设 3600 秒,用
3600 + rand(0, 600)错开过期峰 - 本地缓存兜底:复杂业务可先查
apcu,命中则跳过 Redis,减少网络开销(需额外装 APCu 扩展) - 别依赖
Cache::add()做锁 —— 它不是原子 setnx,高并发下可能失效;真要锁,用Redis::lock()或Cache::lock()(Laravel 8.0+)
真正卡住人的从来不是“怎么连上 Redis”,而是缓存键设计不合理、没防穿透、没压测过期洪峰——这些细节不提前想清楚,上线后查 slowlog 和 INFO memory 就晚了。











