.NET 9中如何使用HybridCache更新现有缓存?
HybridCache 更新内存缓存集合的替代方案
HybridCache的设计逻辑和MemoryCache不同:它默认会对存储的对象进行序列化,即便底层依赖MemoryCache,取出的也是对象的序列化副本而非原引用——这就是为什么你没法像操作MemoryCache那样直接修改缓存中的集合(修改副本不会同步回缓存),同时它也没有TryGetValue这类直接获取引用的方法。
如果不想删除缓存键再重新添加,可采用以下两种方案:
方案一:获取-修改-重写(覆盖式更新)
先从HybridCache中获取集合的副本,修改后直接调用SetAsync(或同步版Set)覆盖原缓存项,无需删除键。示例代码:
// 初始化缓存集合 var initialList = new List<string> { "a", "b", "c" }; await hybridCache.SetAsync("Key", initialList); // 更新集合 var cachedList = await hybridCache.GetAsync<List<string>>("Key") ?? new List<string>(); cachedList.Add("d"); await hybridCache.SetAsync("Key", cachedList); // 验证结果 var updatedList = await hybridCache.GetAsync<List<string>>("Key");
注意:这种方式要处理并发更新问题,如果多个请求同时修改,可能会出现覆盖丢失的情况,可配合锁(如SemaphoreSlim)来保证线程安全。
方案二:使用线程安全的可变包装类
如果需要更频繁的修改,可以将集合包装在一个线程安全的容器中,存入HybridCache后,每次修改直接操作容器内的集合,最后手动触发缓存刷新(或依赖HybridCache的过期机制)。示例:
// 定义线程安全的包装类 public class ThreadSafeListWrapper<T> { private readonly List<T> _list = new(); private readonly object _lock = new(); public void Add(T item) { lock (_lock) { _list.Add(item); } } public List<T> GetSnapshot() { lock (_lock) { return new List<T>(_list); } } } // 使用示例 var wrapper = new ThreadSafeListWrapper<string>(); wrapper.Add("a"); wrapper.Add("b"); wrapper.Add("c"); await hybridCache.SetAsync("Key", wrapper); // 修改集合 var cachedWrapper = await hybridCache.GetAsync<ThreadSafeListWrapper<string>>("Key"); if (cachedWrapper != null) { cachedWrapper.Add("d"); // 手动刷新缓存,确保修改后的状态被序列化保存 await hybridCache.SetAsync("Key", cachedWrapper); }
这个方案的核心是:包装类内部维护线程安全的集合,修改后需要主动将整个包装类重新存入缓存,确保序列化后的内容是最新的。
额外建议
如果你的场景中集合需要频繁修改,且不需要HybridCache的分布式/持久化能力,直接单独使用MemoryCache存储这类集合会更高效——毕竟HybridCache的序列化开销对于频繁修改的引用类型来说并不友好。
内容的提问来源于stack exchange,提问作者Zulander
相关产品推荐
相关产品推荐

