Laravel 11 多库缓存隔离核心是显式控制缓存键空间与存储位置,需为每个数据库连接单独配置 cache store 并绑定唯一 prefix,配合 store 指定、连接标识注入、Redis database 隔离及事务后主动清理,避免键冲突与缓存污染。

在 Laravel 11 多库场景下做数据库缓存隔离,核心是让不同数据库连接产生的查询结果不互相干扰——不是靠“自动识别库名”,而是靠**显式控制缓存键空间与存储位置**。Laravel 本身不为每个 DB 连接自动分配独立缓存前缀或存储,必须手动配置。
按连接名区分缓存存储
这是最直接、最可控的方式:为每个数据库连接(如 mysql、pgsql_tenant_a、sqlite_logs)单独配置一个缓存 store,并绑定唯一前缀。
- 在
config/cache.php的'stores'数组中新增对应项,例如:
<?php
// config/cache.php
'stores' => [
'redis_mysql' => [
'driver' => 'redis',
'connection' => 'cache',
'prefix' => 'db:mysql:',
],
'redis_tenant_a' => [
'driver' => 'redis',
'connection' => 'cache',
'prefix' => 'db:tenant_a:',
],
]
- 在业务中使用时,显式指定 store:
Cache::store('redis_mysql')
->remember('user_count', 3600, fn() => DB::connection('mysql')->table('users')->count());
Cache::store('redis_tenant_a')
->remember('order_total', 3600, fn() => DB::connection('pgsql_tenant_a')->table('orders')->sum('amount'));
用模型连接属性+自定义缓存键
若使用 Eloquent 模型且已通过 $connection 属性指定了库,可在模型中统一注入连接标识,避免硬编码 store 名。
- 在基础模型中覆盖
getCacheKeyPrefix()方法:
class BaseModel extends Model
{
protected function getCacheKeyPrefix(): string
{
return 'db:' . $this->connection . ':';
}
}
- 然后在查询中构造带前缀的键:
$key = (new User())->getCacheKeyPrefix() . 'active_list';
Cache::remember($key, 3600, fn() => User::where('active', 1)->get());
避免缓存污染的关键细节
多库共用同一 Redis 实例时,仅靠前缀不够;需配合驱动级隔离或逻辑清理策略。
- 确保各 store 使用不同 Redis
database(如'database' => 2和'database' => 3),物理上隔开数据 - 不依赖
Cache::flush()全局清空——它会误删其他库的缓存;改用Cache::store('xxx')->flush() - 若用 tags(仅 redis/memcached 支持),可按连接打标:
Cache::tags(['db:mysql'])->put(...),再按标清理 - 慎用
remember()默认键生成逻辑:它基于 SQL 字符串哈希,不同库若 SQL 相同,键就冲突;务必显式传入带连接上下文的键名
事务与读写分离下的缓存一致性提醒
Laravel 11 中,事务内所有查询强制走主库,但缓存仍可能被从库查询写入。这会导致“主库刚更新,缓存里还是旧从库结果”的问题。
- 涉及写操作后,应主动清除相关缓存(如用模型观察器监听
saving/deleted) - 对强一致性要求高的数据(如用户余额),跳过缓存,或只允许主库读取路径命中缓存
- 不要在事务闭包里调用
remember()——事务未提交时缓存写入,可能缓存到未确认状态


















