laravel-mongodb缓存需确保php mongodb扩展和jenssegers/mongodb包已安装启用,正确配置database.php与cache.php中mongodb驱动及stores.mongodb完整参数,手动创建expires_at ttl索引,并注意序列化限制与大对象缓存策略。

确认 laravel-mongodb 扩展已正确安装并启用
没装 mongodb PHP 扩展或没引入 jenssegers/mongodb 包,MongoStore 类根本不会被自动加载,后续所有配置都白搭。Laravel 不会报“驱动不存在”,而是静默 fallback 到 file 或抛出未定义类错误。
检查点包括:
-
php -m | grep mongodb确保 PHP 扩展已启用 -
composer show jenssegers/mongodb确认包版本兼容当前 Laravel(如 Laravel 11 需用^4.0) -
config/database.php中存在有效的mongodb连接配置,且能通过php artisan tinker连通:(new \Jenssegers\Mongodb\Connection(...))->getMongoClient()
在 config/cache.php 中注册 mongodb 驱动并设置为默认
不能只改 'default' => 'mongodb',必须完整声明 stores.mongodb 配置块,否则 Laravel 初始化缓存时会因找不到 driver 配置而崩溃。
关键字段缺一不可:
-
driver必须是字符串'mongodb',不是'mongo'或其他别名 -
connection值必须与config/database.php中的 MongoDB 连接名完全一致(如'mongodb') -
collection和lock_collection建议显式指定,避免使用默认名导致权限或清理冲突 -
lock_timeout若业务有长耗时任务(如导出),需调大,否则锁可能提前释放引发并发覆盖
示例片段:
'stores' => [
'mongodb' => [
'driver' => 'mongodb',
'connection' => 'mongodb',
'collection' => 'cache',
'lock_connection' => 'mongodb',
'lock_collection' => 'cache_locks',
'lock_timeout' => 300,
],
],
'default' => 'mongodb',
手动创建 TTL 索引防止缓存堆积
MongoDB 不会自动为 expires_at 字段建索引,MongoStore::createTTLIndex() 也**不会在每次请求时自动调用**。没索引 → 过期文档不自动删除 → cache 集合无限膨胀 → 查询变慢甚至 OOM。
推荐做法:
- 部署时执行一次:在 Artisan 命令中调用
(new \Jenssegers\Mongodb\Cache\MongoStore(...))->createTTLIndex() - 或直接在 MongoDB Shell 手动建:
db.cache.createIndex({ "expires_at": 1 }, { "expireAfterSeconds": 0 }) - 验证是否生效:
db.cache.getIndexes()查看是否存在expires_at_1索引
注意 MongoStore 的序列化行为和值结构限制
MongoStore::put() 内部会对值做 serialize(),但 MongoDB 文档有 16MB 上限,且不支持 PHP 资源、闭包、部分对象(如 DB 连接实例)。若缓存大数组或模型集合,容易触发 MaxKeySizeExceeded 错误。
规避方式:
- 缓存前用
json_encode()+json_decode()替代原生序列化(需重写serialize/unserialize逻辑) - 对大对象做分片缓存,例如按 ID 段落拆成多个 key:
users:chunk:1,users:chunk:2 - 避免缓存 Eloquent 模型实例,改用
$model->toArray()或$model->toJson()
另外,forever() 并非真永久 —— 它仍会写入 expires_at 字段(设为远期时间),仍受 TTL 索引管理,只是不会被 forget() 之外的机制清理。











