MemoryCache 是 .NET 内置线程安全内存缓存,适用于单机高频读低频写场景;需通过 DI 注册和注入使用,支持绝对/滑动过期、优先级、淘汰回调等特性,但不支持自动刷新,且数据进程内有效、重启丢失。
MemoryCache 是 .NET 内置的线程安全内存缓存组件,适用于单机应用中临时存储高频读、低频写的数据,比如配置项、字典表、API 响应结果等。它不依赖外部服务(如 Redis),开箱即用,但数据只存在于当前进程内存中,重启即丢失。
在 .NET 5+ 或 .NET Core 项目中,Microsoft.Extensions.Caching.Memory 已内置,无需额外安装 NuGet 包(旧版 .NET Framework 需手动安装 Microsoft.Extensions.Caching.Memory)。
推荐通过依赖注入使用缓存,而不是手动 new 实例 —— 这样能保证生命周期统一、线程安全且便于测试:
Program.cs(.NET 6+)或 Startup.cs 中注册:builder.Services.AddMemoryCache(); // 注册为单例服务
IMemoryCache:public class ProductService
{
private readonly IMemoryCache _cache;
public ProductService(IMemoryCache cache)
{
_cache = cache;
}}
2. 存储与读取缓存项
MemoryCache 使用键值对方式操作,键必须是 object 类型(通常用 string),值任意类型。注意:键需全局唯一,建议加前缀避免冲突(如 "product:1001")。
_cache.Set("product:1001", product, new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(TimeSpan.FromMinutes(30)) // 30 分钟后绝对过期
.SetSlidingExpiration(TimeSpan.FromMinutes(10)) // 10 分钟内无访问则过期
.SetPriority(CacheItemPriority.Normal) // 优先级,内存紧张时决定淘汰顺序
.RegisterPostEvictionCallback((key, value, reason, state) =>
{
Console.WriteLine($"缓存 {key} 因 {reason} 被移除");
}));if (_cache.TryGetValue("product:1001", out Product? cachedProduct))
{
return cachedProduct;
}
// 缓存未命中,查数据库并写入
var product = _db.Products.Find(id);
_cache.Set("product:1001", product, TimeSpan.FromMinutes(30));
return product;MemoryCache 不支持自动后台刷新(如定时重加载),但可通过封装 + 定时任务或“懒加载+滑动过期”模拟软刷新效果。
GetOrCreate 原子操作,确保同一键只执行一次工厂方法:return _cache.GetOrCreate("config:site", entry =>
{
entry.SetAbsoluteExpiration(TimeSpan.FromMinutes(5));
return LoadSiteConfigFromDb(); // 此方法只会被调用一次(并发下也只一次)
});WeakReference 包装或改用文件/分布式缓存_cache.Remove("key") 或 _cache.Compact(percentage: 50) 主动释放约 50% 占用空间(按优先级和过期时间估算)nameof + ID 组合生成键SizeLimit 并配合 Size 选项new MemoryCache(new MemoryCacheOptions()) 创建轻量实例,无需 DI 容器基本上就这些。MemoryCache 上手简单,关键在于合理设过期策略、避免缓存污染、不滥用大对象 —— 控制好这几点,日常业务缓存需求基本都能稳稳覆盖。