HybridCache 的 Tag 删除不自动级联,需手动配置 EnableTagSupport、确保 L2 存储支持并主动清理 L1;GetOrCreateAsync 中须在 factory 内设置 Tags;RemoveByTagAsync 默认静默失败且不跨实例广播。

HybridCache 的 Tag 不是“删除时自动级联”,得手动指定
很多人以为给缓存项打上 Tag(比如 "user:1001" 或 "order:pending"),调用 RemoveByTagAsync("user:1001") 就能自动清掉所有带这个标签的条目——但 HybridCache 默认不提供这种“全局标签扫描”能力。它的 Tag 本质是元数据,只在你显式使用 SetAsync 时通过 CacheEntryOptions.Tags 写入,且清除必须配合 RemoveByTagAsync + 后端存储支持。
关键点在于:Redis 作为 L2 时,RemoveByTagAsync 能生效;但若只用 MemoryCache 做 L1(无持久化索引),该方法实际什么也不做——因为内存里没维护标签到 key 的反向映射。
- 必须确保 L2 存储(如 Redis)启用了标签支持,且配置了
HybridCacheOptions.EnableTagSupport = true - 调用
RemoveByTagAsync前,要确认目标缓存项确实是在 L2 中写入的(即至少触发过一次回源并成功写入 Redis) - 本地层(L1)不会自动同步标签删除动作,后续读取仍可能命中旧的本地副本,需搭配
SetAbsoluteExpiration或主动调用RemoveAsync清理 L1
GetOrCreateAsync 里写 Tags 得在回调函数中设置,不能靠外部传参
GetOrCreateAsync 是 HybridCache 最常用的入口,但它本身不接受 CacheEntryOptions 参数。想让生成的缓存项带标签,必须在 factory 回调里手动构造 CacheEntryOptions 并赋值 Tags,否则标签会丢失。
错误写法:await cache.GetOrCreateAsync("user:1001", _ => LoadUserAsync(1001)) —— 这样生成的项没有标签。
正确写法:
await cache.GetOrCreateAsync("user:1001", async context => {<br> context.Options.Tags = new[] { "user", "user:1001" };<br> return await LoadUserAsync(1001);<br>});
- 标签数组内容建议用稳定字符串,避免拼接运行时变量(如
DateTime.Now.ToString()),否则失效逻辑不可控 - 如果
LoadUserAsync抛异常,context.Options设置无效,该项不会被缓存,也不会写入任何标签 - 并发场景下,多个线程同时触发同一个 key 的
GetOrCreateAsync,只有第一个成功写入的会携带你设置的标签;其余线程读到的是已存在的缓存项,其标签以首次写入为准
多实例部署时,RemoveByTagAsync 只清当前节点看到的 L2,L1 需额外广播
HybridCache 的标签删除默认只作用于配置的分布式后端(如 Redis),不触达其他应用实例的本地内存缓存(L1)。也就是说,你在实例 A 调用 RemoveByTagAsync("product:2001"),实例 B 的 MemoryCache 里还留着旧值,下次读取直接返回,造成数据不一致。
- 没有内置广播机制,得自己加:例如用 Redis Pub/Sub 在标签删除后发通知,各实例监听并调用
RemoveAsync清本地项 - 也可以放弃 L1 标签强一致性,改用较短的
SlidingExpiration(如 30 秒),让本地副本自然过期,代价是少量请求会多走一次 L2 - 若业务对实时性要求极高,干脆关掉 L1(只配 L2),或把 HybridCache 当纯分布式缓存用——此时
RemoveByTagAsync就是可靠的
标签失效失败时,RemoveByTagAsync 默认静默失败,不抛异常
当 Redis 不可用、连接超时或权限不足时,RemoveByTagAsync 不会抛出 RedisConnectionException 或类似异常,而是直接返回 Task.CompletedTask。你从调用结果完全看不出是否真的删掉了东西。
这意味着:你以为清掉了“用户资料”相关所有缓存,其实什么都没发生,而前端还在展示旧头像、旧昵称。
- 必须自行检查底层 Redis 客户端日志,或启用
HybridCacheOptions.Logger捕获内部警告(如"Failed to remove entries by tag 'xxx' in distributed cache") - 生产环境建议包装一层:在调用
RemoveByTagAsync后,立刻用GetAsync随机抽查 1–2 个已知带该标签的 key,验证是否真被清除 - 不要依赖“调用成功 = 生效”,尤其在发布后批量刷新场景下,这类静默失败最容易埋雷


















