c# 如何用lock解決緩存擊穿
背景
緩存擊穿是指緩存中沒有但數(shù)據(jù)庫中有的數(shù)據(jù)(一般是緩存時(shí)間到期),這時(shí)由于并發(fā)用戶特別多,同時(shí)讀緩存沒讀到數(shù)據(jù),又同時(shí)去數(shù)據(jù)庫去取數(shù)據(jù),引起數(shù)據(jù)庫壓力瞬間增大,造成過大壓力。
解決方案
1、設(shè)置熱點(diǎn)數(shù)據(jù)永遠(yuǎn)不過期。
2、加互斥鎖,互斥鎖參考代碼如下:
2.1、根據(jù)key生成object()
private static object GetMemoryCacheLockObject(string key)
{
string cacheLockKey = string.Format(MemoryCacheLockObjectFormat, key);
lock (CacheObject)
{
var lockObject = CacheObject[cacheLockKey];
if (lockObject == null)
{
// 取得每個(gè) Key專屬的 lock object;若同時(shí)有多個(gè) thread要求相同資料,只會(huì)(到資料庫)查第一次,剩下的從 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,強(qiáng)制重查
result = null;
}
if (result == null)
{
//執(zhí)行取得資料的委派作業(yè)
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();
}
}
總結(jié)說明
1、緩存中有數(shù)據(jù),直接走下述代碼就返回結(jié)果了
T result = CacheObject[key] as T;
2、緩存中沒有數(shù)據(jù),第1個(gè)進(jìn)入的線程,獲取鎖并從數(shù)據(jù)庫去取數(shù)據(jù),沒釋放鎖之前,其他并行進(jìn)入的線程會(huì)等待,再重新去緩存取數(shù)據(jù)。這樣就防止都去數(shù)據(jù)庫重復(fù)取數(shù)據(jù),重復(fù)往緩存中更新數(shù)據(jù)情況出現(xiàn)。
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、取得每個(gè) Key專有的 lock object;若同時(shí)有多個(gè) thread要求相同資料,只會(huì)(到數(shù)據(jù)庫)查第一次,剩下的從 cache讀取。
string cacheLockKey = string.Format(MemoryCacheLockObjectFormat, key);
lock (CacheObject)
{
var lockObject = CacheObject[cacheLockKey];
if (lockObject == null)
{
// 取得每個(gè) Key專屬的 lock object;若同時(shí)有多個(gè) thread要求相同資料,只會(huì)(到資料庫)查第一次,剩下的從 cache讀取
lockObject = new object();
以上就是c# 如何用lock解決緩存擊穿的詳細(xì)內(nèi)容,更多關(guān)于c# lock解決緩存擊穿的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解C#如何實(shí)現(xiàn)隱式類型轉(zhuǎn)換
Result?類型是許多編程語言中處理錯(cuò)誤的常用方式,包括?C#?的?dotNext?庫。在本文中,我們將通過例子回顧?C#?中?using?語句和隱式類型轉(zhuǎn)換的使用,感興趣的可以了解一下2023-01-01
Winform項(xiàng)目中使用FastReport.Net報(bào)表控件
這篇文章介紹了Winform項(xiàng)目中使用FastReport.Net報(bào)表控件的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06
C# 中將數(shù)值型數(shù)據(jù)轉(zhuǎn)換為字節(jié)數(shù)組的方法
C# 中將數(shù)值型數(shù)據(jù)轉(zhuǎn)換為字節(jié)數(shù)組的方法,需要的朋友可以參考一下2013-05-05
Visual C#類的定義及實(shí)現(xiàn)方法實(shí)例解析
這篇文章主要介紹了Visual C#類的定義及實(shí)現(xiàn)方法實(shí)例解析,對(duì)于新手來說有不錯(cuò)的借鑒學(xué)習(xí)價(jià)值,需要的朋友可以參考下2014-07-07

