:::info 概念的概念
- 缓存命中
- 缓存命中率
- 缓存数据不一致
:::
客户端缓存
//Action上面加ResponseCache特性,设置客户端缓存多少秒
[ResponseCache(Duration =20)]
[HttpGet("Now")]
public string Now()
{
return DateTime.Now.ToString();
}
服务端缓存
:::info 通过在program.cs注册使用
app.UseResponseCaching(); //添加服务器缓存
在app.MapControllers();前面添加
如果有用到app.useCors()
app.useCors() 一定要写在缓存之前。
:::
内存缓存(In-memory cache)
:::info
- 把缓存数据放到应用程序的内存。内存缓存中保存的是以系列的键值对,就像Dictionary类型一样。
- 内存缓存的数据保存在当前运行的网站程序的内存中,是和进程相关的。因为在Web服务器中,多个不同网站是运行在不同的进程中的,因此不同网站的内存缓存是不会相互干扰的,而且网站重启后,内存缓存中的所有数据也就都被清空了。
缓存的过期时间
- 解决方法:在数据改变的时候调用remove或者set来删除或者修改缓存(优点:及时);过期时间(只要过期时间比较短,缓存数据不一致的情况也不会持续很长时间)
- 两种过期时间策略:绝对过期时间、滑动过期时间
//设置绝对过期时间,到时间点后就会自动过期
e.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(10);
//滑动过期时间,在时间段内被请求就会自动续命,在时间段内没有被请求,就会过期
e.SlidingExpiration = TimeSpan.FromSeconds(10);
缓存雪崩问题
- 缓存集中过期引起缓存雪崩
解决办法:在基础过期时间之上,在加一个随机的过期时间
e.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(Random.Shared.Next(10, 15));
:::
builder.Services.AddMemoryCache(); //注册内存缓存服务
//构造函数注入缓存服务
private readonly IMemoryCache memoryCache;
public DemoController(IMemoryCache memoryCache)
{
this.memoryCache = memoryCache;
}
[HttpGet("GetByIdCache/{id?}")]
public async Task<ActionResult<Book?>> GetByIdCache(long id)
{
Console.WriteLine("开始GetByIdCache");
Book? book = await memoryCache.GetOrCreateAsync("Book" + id, async (e) =>
{
Console.WriteLine($"缓存里没找到,到数据库查询数据id={id}");
//设置绝对过期时间,到时间点后就会自动过期
// e.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(10);
//滑动过期时间,在时间段内被请求就会自动续命,在时间段内没有被请求,就会过期
e.SlidingExpiration = TimeSpan.FromSeconds(10);
return await MyDBContext.GetBookByIdAsync(id);
});
Console.WriteLine("GetOrCreateAsync结果" + book);
if (book == null)
{
return NotFound($"没有ID为[{id}]的书");
}
return book;
}