在 Web API 开发中,频繁访问数据库或第三方服务可能会带来性能瓶颈。为了提升接口响应速度并减轻后端压力,使用缓存是非常有效的优化手段。
本文将带你快速上手 ASP.NET Core 提供的内存缓存(IMemoryCache
),无需安装额外库,轻量、简单、适合中小项目
IMemoryCache
是 ASP.NET Core 自带的缓存机制,使用服务器内存来存储数据对象,单机部署即可使用,无需 Redis 等中间件。
它非常适合以下场景:
中小型项目
单台服务器部署
临时性或短期缓存需求(如列表页缓存、字典表缓存)
IMemoryCache
默认已包含在 ASP.NET Core 中,仅需在 Program.cs
注册:
builder.Services.AddMemoryCache();
以下是一个简单的控制器示例,缓存产品列表 5 分钟:
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
[ApiController]
[Route("api/[controller]")]
public class ProductController : ControllerBase
{
private readonly IMemoryCache _cache;
public ProductController(IMemoryCache cache)
{
_cache = cache;
}
[HttpGet("GetAll")]
public IActionResult GetAll()
{
const string cacheKey = "product_list";
// 尝试从缓存中读取
if (_cache.TryGetValue(cacheKey, out List cachedProducts))
{
return Ok(new { fromCache = true, data = cachedProducts });
}
// 模拟从数据库读取数据
var productsFromDb = new List { "Apple", "Banana", "Orange" };
// 设置缓存项(滑动过期 5 分钟)
var cacheOptions = new MemoryCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromMinutes(5));
_cache.Set(cacheKey, productsFromDb, cacheOptions);
return Ok(new { fromCache = false, data = productsFromDb });
}
}
IMemoryCache接口是ASP.NET Core 中用于本地内存缓存的核心接口,位于命名空间Microsoft.Extensions.Caching.Memory
下。
它本质上是一个轻量级的、线程安全的键值对缓存容器,你可以通过它来存取缓存项,而不需要关心底层缓存机制的实现。
下面是对它各个成员的详细讲解:
1.bool TryGetValue(object key, out object? value)
尝试从缓存中获取一个键对应的值。
if (_memoryCache.TryGetValue("product_list", out var value))
{
// value 是 object 类型,通常你需要强制转换一下
var products = value as List;
}
如果 key
存在于缓存中,则返回 true
,并将其值赋给 value
如果不存在,返回 false
,value
是 null
2.ICacheEntry CreateEntry(object key)
创建一个新的缓存项,或更新已有项。
.Set()
封装版本)var entry = _memoryCache.CreateEntry("product_list");
entry.Value = new List { "Apple", "Banana" };
entry.SlidingExpiration = TimeSpan.FromMinutes(5);
entry.Dispose(); // 必须手动 Dispose,否则不会生效!
注意:
CreateEntry()
返回的是一个ICacheEntry
,需要Dispose()
才能提交。通常你不需要直接用这个方法,而是使用更方便的Set()
方法(实际上它内部就是调用了这个方法并自动处理)。
3.void Remove(object key)
显式移除某个缓存项。
_memoryCache.Remove("product_list");
数据更新时主动清除旧缓存
控制缓存大小
用户退出登录后清除用户相关缓存
4.MemoryCacheStatistics? GetCurrentStatistics()
获取当前缓存的统计数据(如命中率、条目数等)。
var stats = _memoryCache.GetCurrentStatistics();
if (stats != null)
{
Console.WriteLine($"Entries: {stats.CurrentEntryCount}, Hits: {stats.TotalHits}");
}
仅在启用了统计时才有意义,在默认
MemoryCacheOptions
下此功能为 关闭状态。
上述成员我们一般不会使用,donet有更高级的封装给我们使用!
虽然 IMemoryCache
提供了上述原始 API,但大多数开发者会用这些 更方便的扩展方法(定义在 MemoryCacheExtensions
类中):
Set
方法(创建或更新)_memoryCache.Set("product_list", data, TimeSpan.FromMinutes(5));
Get
方法(读取)var list = _memoryCache.Get>("product_list");
GetOrCreate
方法(读取或创建)这个方法是最推荐使用的,先尝试从缓存获取,如果缓存没有那么回调方法里面再从数据库里面查找,
如果数据库没有别忘了抛出异常,避免缓存null
var result = _memoryCache.GetOrCreate("product_list", entry =>
{
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5);
return GetProductsFromDb(); // 如果没缓存,就调用这个方法
});
IMemoryCache
是 ASP.NET Core 中的本地缓存接口,提供最基本的存取能力(TryGetValue、CreateEntry、Remove)和可选统计功能(GetCurrentStatistics),但推荐使用其扩展方法Set
、Get
、GetOrCreate
来更高效地完成常规缓存需求。
MemoryCacheEntryOptions
提供了多种配置方式:
方法 | 说明 |
---|---|
SetSlidingExpiration |
如果缓存一段时间内没被访问就自动过期 |
SetAbsoluteExpiration |
缓存数据在指定时间后无论如何都过期 |
SetPriority |
设置缓存项在清除时的优先级 |
RegisterPostEvictionCallback |
缓存被移除时触发回调函数 |
只适用于单机,如果你使用的是集群或容器化部署,请考虑分布式缓存(如 Redis)。
缓存 key 应该具有唯一性,避免与其他模块冲突。
不要缓存过大的数据,避免内存膨胀。
对于会频繁更新的数据,需做好缓存失效机制设计。
为避免控制器代码臃肿,推荐将缓存逻辑封装进服务类中,控制器只负责返回结果。
public class ProductService
{
private readonly IMemoryCache _cache;
public ProductService(IMemoryCache cache)
{
_cache = cache;
}
public List GetAllProducts()
{
if (_cache.TryGetValue("product_list", out List products))
return products;
var list = new List { "Apple", "Banana", "Orange" };
_cache.Set("product_list", list, TimeSpan.FromMinutes(5));
return list;
}
}
优点 | 缺点 |
---|---|
快速、轻量 | 仅支持单节点 |
使用简单 | 数据丢失风险(如进程重启) |
零依赖 | 不适合大规模持久缓存 |
对于中小型的 Web API 项目,IMemoryCache
是一个非常合适的选择。在性能与复杂度之间取得平衡,能让你在几行代码内大幅提升响应速度!