首页 新闻 会员 周边

.NET HybridCache 缓存到内存时怎么也会进行序列化

0
悬赏园豆:10 [已解决问题] 解决于 2026-04-06 13:22

最近在 ASP.NET Core 10 项目中遇到的问题,出现问题的 C# 代码如下:

var cacheOptions = new HybridCacheEntryOptions
{
    LocalCacheExpiration = TimeSpan.FromMinutes(1),
    Flags = HybridCacheEntryFlags.DisableDistributedCache
};

return await hybridCache.GetOrCreateAsync(
    cacheKey,
    async token => await GetRuleListByCheckee<TCheckee>(),
    cacheOptions);

因为序列化失败,才发现 HybridCache 在使用内存缓存(in-memory cache)也进行了序列化操作

MessagePack.MessagePackSerializationException: Failed to serialize ...
 ---> MessagePack.FormatterNotRegisteredException: ...
   at MessagePack.FormatterResolverExtensions.Throw(Type t, IFormatterResolver resolver)
   at MessagePack.Formatters.ListFormatter`1.Serialize(MessagePackWriter& writer, List`1 value, MessagePackSerializerOptions options)
   at MessagePack.MessagePackSerializer.Serialize[T](MessagePackWriter& writer, T value, MessagePackSerializerOptions options)
   --- End of inner exception stack trace ---
   at MessagePack.MessagePackSerializer.Serialize[T](MessagePackWriter& writer, T value, MessagePackSerializerOptions options)
   at MessagePack.MessagePackSerializer.Serialize[T](IBufferWriter`1 writer, T value, MessagePackSerializerOptions options, CancellationToken cancellationToken)
   at Cnblogs.Cache.Hybrid.Extensions.HybridCacheMessagePackSerializer`1.Serialize(T value, IBufferWriter`1 target)
   at Microsoft.Extensions.Caching.Hybrid.Internal.DefaultHybridCache.TrySerialize[T](T value, BufferChunk& buffer, IHybridCacheSerializer`1& serializer)
   at Microsoft.Extensions.Caching.Hybrid.Internal.DefaultHybridCache.StampedeState`2.BackgroundFetchAsync()
   at Microsoft.Extensions.Caching.Hybrid.Internal.DefaultHybridCache.StampedeState`2.<UnwrapReservedAsync>g__AwaitedAsync|18_0(ILogger log, Task`1 task)

如何让 HybridCache 不进行这个序列化操作?

dudu的主页 dudu | 高人七级 | 园豆:23002
提问于:2026-04-06 12:02
< >
分享
最佳答案
0

通过 HybridCache 的开源代码 DefaultHybridCache.StampedeStateT.cs#L330 知道了,满足以下条件才不进行序列化


// If we're writing this value *anywhere*, we're going to need to serialize; this is obvious
// in the case of L2, but we also need it for L1, because MemoryCache might be enforcing
// SizeLimit (we can't know - it is an abstraction), and for *that* we need to know the item size.
// Likewise, if we're writing to a MutableCacheItem, we'll be serializing *anyway* for the payload.
//
// Rephrasing that: the only scenario in which we *do not* need to serialize is if:
// - it is an ImmutableCacheItem (so we don't need bytes for the CacheItem, L1)
// - we're not writing to L2
CacheItem cacheItem = CacheItem;
bool skipSerialize = cacheItem is ImmutableCacheItem<T> && (activeFlags & FlagsDisableL1AndL2Write) == FlagsDisableL1AndL2Write;
dudu | 高人七级 |园豆:23002 | 2026-04-06 13:21
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册