这篇文章主要介绍了c# 如何用lock解决缓存击穿,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下
背景
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
解决方案
1、设置热点数据永远不过期。
2、加互斥锁,互斥锁参考代码如下:
2.1、根据key生成object()
private static object GetMemoryCacheLockObject(string key)
{
string cacheLockKey = string.Format(MemoryCacheLockObjectFormat, key);
lock (CacheObject)
{
var lockObject = CacheObject[cacheLockKey];
if (lockObject == null)
{
// 取得每個 Key專屬的 lock object;若同時有多個 thread要求相同資料,只會(到資料庫)查第一次,剩下的從 cache讀取
lockObject = new object();
CacheObject.Set(
cacheLockKey,
lockObject,
new System.Runtime.Caching.CacheItemPolicy()
{
AbsoluteExpiration = DateTimeOffset.UtcNow.AddMinutes(10)
}
);
}
return lockObject;
}
}
2.2、lock住GetMemoryCacheLockObject(key)
public T Get<T>(string key, Func<T> getDataWork, TimeSpan absoluteExpireTime, bool forceRefresh = false, bool returnCopy = true) where T : class
{
try
{
lock (GetMemoryCacheLockObject(key))
{
/*
System.ArgumentNullException: Value cannot be null.
at System.Threading.Monitor.Enter(Object obj)
at BQoolCommon.Helpers.Cache.MemoryCacheLayer.Get[T](String key, Func`1 getDataWork, TimeSpan absoluteExpireTime, Boolean forceRefresh, Boolean returnCopy) in D:\Source\BQoolCommon\BQoolCommon.Helpers\Cache\MemoryCacheLayer.cs:line 46
*/
T result = CacheObject[key] as T;
if (result != null && forceRefresh)
{// 是否清除Cache,強制重查
result = null;
}
if (result == null)
{
//執行取得資料的委派作業
result = getDataWork();
if (result != null)
{
Set(key, result, absoluteExpireTime);
}
}
if (returnCopy)
{
//複製一份新的參考
string serialize = JsonConvert.SerializeObject(result);
return JsonConvert.DeserializeObject<T>(serialize);
}
else
{
return result;
}
}
}
catch
{
return getDataWork();
}
}
总结说明
1、缓存中有数据,直接走下述代码就返回结果了
T result = CacheObject[key] as T;
2、缓存中没有数据,第1个进入的线程,获取锁并从数据库去取数据,没释放锁之前,其他并行进入的线程会等待,再重新去缓存取数据。这样就防止都去数据库重复取数据,重复往缓存中更新数据情况出现。
try
{
lock (GetMemoryCacheLockObject(key))
{
/*
System.ArgumentNullException: Value cannot be null.
at System.Threading.Monitor.Enter(Object obj)
at BQoolCommon.Helpers.Cache.MemoryCacheLayer.Get[T](String key, Func`1 getDataWork, TimeSpan absoluteExpireTime, Boolean forceRefresh, Boolean returnCopy) in D:\Source\BQoolCommon\BQoolCommon.Helpers\Cache\MemoryCacheLayer.cs:line 46
*/
T result = CacheObject[key] as T;
3、取得每个 Key专有的 lock object;若同时有多个 thread要求相同资料,只会(到数据库)查第一次,剩下的从 cache读取。
string cacheLockKey = string.Format(MemoryCacheLockObjectFormat, key);
lock (CacheObject)
{
var lockObject = CacheObject[cacheLockKey];
if (lockObject == null)
{
// 取得每個 Key專屬的 lock object;若同時有多個 thread要求相同資料,只會(到資料庫)查第一次,剩下的從 cache讀取
lockObject = new object();
以上就是c# 如何用lock解决缓存击穿的详细内容,更多关于c# lock解决缓存击穿的资料请关注得得之家其它相关文章!
沃梦达教程
本文标题为:c# 如何用lock解决缓存击穿
基础教程推荐
猜你喜欢
- 覆盖 Json.Net 中的默认原始类型处理 2022-01-01
- Page.OnAppearing 中的 Xamarin.Forms Page.DisplayAlert 2022-01-01
- 从 VB6 迁移到 .NET/.NET Core 的最佳策略或工具 2022-01-01
- 如何使用OpenXML SDK将Excel转换为CSV? 2022-01-01
- C# - 如何列出发布到 ASPX 页面的变量名称和值 2022-01-01
- C# - 将浮点数转换为整数...并根据余数更改整数 2022-01-01
- 当键值未知时反序列化 JSON 2022-01-01
- 使用 SED 在 XML 标签之间提取值 2022-01-01
- 我什么时候应该使用 GC.SuppressFinalize()? 2022-01-01
- 创建属性设置器委托 2022-01-01