c# 如何用lock解决缓存击穿
背景
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
解决方案
1、设置热点数据永远不过期。
2、加互斥锁,互斥锁参考代码如下:
2.1、根据key生成object()
privatestaticobjectGetMemoryCacheLockObject(stringkey)
{
stringcacheLockKey=string.Format(MemoryCacheLockObjectFormat,key);
lock(CacheObject)
{
varlockObject=CacheObject[cacheLockKey];
if(lockObject==null)
{
//取得每個Key專屬的lockobject;若同時有多個thread要求相同資料,只會(到資料庫)查第一次,剩下的從cache讀取
lockObject=newobject();
CacheObject.Set(
cacheLockKey,
lockObject,
newSystem.Runtime.Caching.CacheItemPolicy()
{
AbsoluteExpiration=DateTimeOffset.UtcNow.AddMinutes(10)
}
);
}
returnlockObject;
}
}
2.2、lock住GetMemoryCacheLockObject(key)
publicTGet(stringkey,Func getDataWork,TimeSpanabsoluteExpireTime,boolforceRefresh=false,boolreturnCopy=true)whereT:class { try { lock(GetMemoryCacheLockObject(key)) { /* System.ArgumentNullException:Valuecannotbenull. atSystem.Threading.Monitor.Enter(Objectobj) atBQoolCommon.Helpers.Cache.MemoryCacheLayer.Get[T](Stringkey,Func`1getDataWork,TimeSpanabsoluteExpireTime,BooleanforceRefresh,BooleanreturnCopy)inD:\Source\BQoolCommon\BQoolCommon.Helpers\Cache\MemoryCacheLayer.cs:line46 */ Tresult=CacheObject[key]asT; if(result!=null&&forceRefresh) {//是否清除Cache,強制重查 result=null; } if(result==null) { //執行取得資料的委派作業 result=getDataWork(); if(result!=null) { Set(key,result,absoluteExpireTime); } } if(returnCopy) { //複製一份新的參考 stringserialize=JsonConvert.SerializeObject(result); returnJsonConvert.DeserializeObject (serialize); } else { returnresult; } } } catch { returngetDataWork(); } }
总结说明
1、缓存中有数据,直接走下述代码就返回结果了
Tresult=CacheObject[key]asT;
2、缓存中没有数据,第1个进入的线程,获取锁并从数据库去取数据,没释放锁之前,其他并行进入的线程会等待,再重新去缓存取数据。这样就防止都去数据库重复取数据,重复往缓存中更新数据情况出现。
try
{
lock(GetMemoryCacheLockObject(key))
{
/*
System.ArgumentNullException:Valuecannotbenull.
atSystem.Threading.Monitor.Enter(Objectobj)
atBQoolCommon.Helpers.Cache.MemoryCacheLayer.Get[T](Stringkey,Func`1getDataWork,TimeSpanabsoluteExpireTime,BooleanforceRefresh,BooleanreturnCopy)inD:\Source\BQoolCommon\BQoolCommon.Helpers\Cache\MemoryCacheLayer.cs:line46
*/
Tresult=CacheObject[key]asT;
3、取得每个Key专有的lockobject;若同时有多个thread要求相同资料,只会(到数据库)查第一次,剩下的从cache读取。
stringcacheLockKey=string.Format(MemoryCacheLockObjectFormat,key);
lock(CacheObject)
{
varlockObject=CacheObject[cacheLockKey];
if(lockObject==null)
{
//取得每個Key專屬的lockobject;若同時有多個thread要求相同資料,只會(到資料庫)查第一次,剩下的從cache讀取
lockObject=newobject();
以上就是c#如何用lock解决缓存击穿的详细内容,更多关于c#lock解决缓存击穿的资料请关注毛票票其它相关文章!