Part4 – (28) 缓存穿透问题
什么是缓存穿透?
传进来一个不存在的Id的,由于缓存里面不存在,每一次都会去数据库查找,造成压力过大。
string cacheKey = "Book" + id;//缓存键
Book? b = memCache.Get<Book?>(cacheKey);
if(b==null)//如果缓存中没有数据
{
//查询数据库,然后写入缓存
b = await dbCtx.Books.FindAsync(id);
memCache.Set(cacheKey, b);
}
缓存穿透的解决方案
1、解决方法:把“查不到”也当成一个数据放入缓存。
2、我们用GetOrCreateAsync方法即可,因为它会把null值也当成合法的缓存值。
string cacheKey = "Book" + id;
var book = await memCache.GetOrCreateAsync(cacheKey, async (e) => {
var b = await dbCtx.Books.FindAsync(id);
logger.LogInformation("数据库查询:{0}",b==null?"为空":"不为空");
return b;
});
logger.LogInformation("Demo5执行结束:{0}", book == null ? "为空" : "不为空");
Part4 – (29) 缓存雪崩问题
缓存雪崩:
1、缓存项集中过期引起缓存雪崩。
2、解决方法:在基础过期时间之上,再加一个随机的过期时间。
缓存数据混乱
public User GetUserInfo()
{
Guid userId=...;//获取当前用户Id
return memCache.GetOrCreate("UserInfo", (e) => {
return ctx.User.Find(userId);
});
}
//解决方法:合理设置key
Part4 – (30)封装内存缓存操作的帮助类
需求:
- IQueryable、IEnumerable等类型可能存在着延迟加载的问题,如果把这两种类型的变量指向的对象保存到缓存中,在我们把它们取出来再去执行的时候,如果它们延迟加载时候需要的对象已经被释放的话,就会执行失败。因此缓存禁止这两种类型。
- 实现随机缓存过期时间
public interface IMemoryCacheHelper
{
TResult? GetOrCreate<TResult>(string cacheKey,
Func<ICacheEntry, TResult?> valueFactory, int expireSeconds);
Task<TResult?> GetOrCreateAsync<TResult>(string cacheKey,
Func<ICacheEntry, Task< TResult?>> valueFactory, int expireSeconds);
void Remove(string cacheKey);
}
本文版权归个人技术分享站点所有,发布者:chaoqiang,转转请注明出处:http://www.zhengchaoqiang.com/1505.html