Laravel+Redis缓存场景下,如何按租户匹配清除指定缓存?
Laravel Redis缓存:清除指定租户的所有缓存键
问题原因
Laravel的Cache::forget()方法不支持通配符匹配,只能删除单个明确的缓存键,所以Cache::forget('*:'.$tenant)不会生效。下面提供三种可行的解决方案:
方案1:使用Redis SCAN命令批量删除(适配现有代码)
直接通过Redis实例遍历匹配租户的所有缓存键并删除,适合不想大规模修改现有缓存逻辑的场景。注意避免使用KEYS命令,它会在Redis数据量大时阻塞服务,改用SCAN渐进式遍历:
// 获取Redis缓存实例 $redis = Cache::getRedis(); // 初始化迭代器,遍历所有匹配 "*:$tenant" 的键 $iterator = null; do { // 每次扫描1000个键,可根据实际调整COUNT值 $result = $redis->scan($iterator, 'MATCH', "*:$tenant", 'COUNT', 1000); if (!empty($result[1])) { // 批量删除匹配到的键 $redis->del(...$result[1]); } } while ($iterator > 0);
方案2:用Redis哈希表组织租户缓存(结构更合理)
将单个租户的所有缓存数据存入同一个Redis哈希表中,删除时直接删除整个哈希表即可,操作更高效:
存储缓存
// 哈希表键名格式:tenant:{租户ID}:cache $hashKey = "tenant:$tenant:cache"; $cacheKey = 'dep_count'; // 从哈希表获取缓存,不存在则计算并存入 $department_count = Cache::getRedis()->hGet($hashKey, $cacheKey); if (!$department_count) { $department_count = Department::where('is_active', 'yes') ->where('tenantID', $tenant) ->count(); // 设置哈希表字段,同时可以单独给字段设置过期时间(如果需要) Cache::getRedis()->hSet($hashKey, $cacheKey, $department_count); // 给整个哈希表设置过期时间 Cache::getRedis()->expire($hashKey, 60 * 60 * 24); }
清除租户所有缓存
$hashKey = "tenant:$tenant:cache"; Cache::getRedis()->del($hashKey);
方案3:使用Laravel缓存标签(最优雅的Laravel原生方案)
Laravel缓存标签支持批量清除同一标签下的所有缓存,Redis驱动原生支持该功能,代码更简洁:
存储带标签的缓存
$department_count = Cache::tags(["tenant:$tenant"]) ->remember('dep_count', 60 * 60 * 24, function () use ($tenant) { return Department::where('is_active', 'yes') ->where('tenantID', $tenant) ->count(); });
清除租户所有缓存
Cache::tags(["tenant:$tenant"])->flush();
内容的提问来源于stack exchange,提问作者Herman Ceaser
相关产品推荐
相关产品推荐

