Cache::tag()清除标签缓存必须用Cache::tag('xxx')->clear(),Redis下需配置tag_prefix与prefix对齐,多标签是“或”逻辑,批量操作应避免KEYS阻塞。

Cache::tag() 清除标签缓存必须显式调用
ThinkPHP 的 Cache::clear() 或命令行 php think clear --all 对带标签的缓存完全无效——哪怕你用了 cache('user:1', $data, ['tag' => 'user']),这些命令也扫不到它。标签缓存是独立索引层,必须走 Cache::tag('xxx')->clear() 才能触发清理逻辑。
Redis 驱动下 tag 清理依赖 prefix 和 tag_prefix 配置
Redis 模式下,Cache::tag('user')->clear() 能否生效,取决于两个关键配置是否对齐:
-
config('cache.stores.redis.prefix'):缓存主键前缀,如think_cache: -
config('cache.stores.redis.tag_prefix'):标签索引专用前缀,如tp_tag:(TP6+ 默认未设,需手动补)
若 tag_prefix 为空,Cache::tag('user')->clear() 会尝试删 tp_tag:user 这类 key,但实际 Redis 里存的是 think_cache:tag:user 或其他格式,导致“删了却没清掉”。务必在 config/cache.php 的 redis store 中显式定义:'tag_prefix' => 'think_cache:tag:'。
多标签组合清除时注意失效逻辑
使用数组传入多个标签,不是“同时命中才清除”,而是“任一标签被清即失效”:
立即学习“PHP免费学习笔记(深入)”;
Cache::tag(['user', 'v2'])->set('profile', $data, 3600);
// 后续执行:
Cache::tag('user')->clear(); // → 'profile' 立即失效
Cache::tag('v2')->clear(); // → 'profile' 同样失效
这种设计适合灰度场景(如清 v2 标签不影响 v1 用户),但容易误判为“没清干净”——其实已清,只是你没测对标签路径。
Redis 大量 tag 缓存时避免 KEYS 阻塞
当手动维护或调试需要批量查某标签下的真实缓存 key(比如确认 user 标签是否残留),别用 KEYS think_cache:tag:user:*——线上库会阻塞。改用游标式 SCAN:
$redis = \think\Cache::connect(['type' => 'redis']);
list($cursor, $keys) = $redis->scan(0, 'think_cache:tag:user:*', 500);
foreach ($keys as $key) {
$realKeys = $redis->sMembers($key); // 标签索引是 set 类型
foreach ($realKeys as $k) {
$redis->del($k);
}
$redis->del($key);
}
真正难的不是写这段代码,而是意识到:你写的 Cache::tag('x')->clear() 在 Redis 里其实做了差不多的事;如果它没生效,大概率是配置错位,而不是代码漏了什么。



















