背景
快取擊穿是指快取中沒有但資料庫中有的資料(一般是快取時間到期),這時由于并發用戶特別多,同時讀快取沒讀到資料,又同時去資料庫去取資料,引起資料庫壓力瞬間增大,造成過大壓力,
解決方案
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();
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/255033.html
標籤:.NET技术
上一篇:高性能資料匯入方案&表過濾器&一對多支持篩選- .NET SqlSugar ORM
下一篇:WPF之x命名空間
