当前位置:首页 >知识 >巧用lock解决缓存击穿的解决方案 这时由于并发用户特别多

巧用lock解决缓存击穿的解决方案 这时由于并发用户特别多

2024-05-13 17:27:15 [百科] 来源:避面尹邢网

巧用lock解决缓存击穿的巧用解决方案

作者:conan5566 存储 存储软件 缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,解决击穿决方同时读缓存没读到数据,缓存又同时去数据库去取数据,巧用引起数据库压力瞬间增大,解决击穿决方造成过大压力。缓存

[[379540]]

本文转载自微信公众号「UP技术控」,巧用作者conan5566  。解决击穿决方转载本文请联系UP技术控公众号。缓存 

巧用lock解决缓存击穿的解决方案 这时由于并发用户特别多

背景

巧用lock解决缓存击穿的解决方案 这时由于并发用户特别多

缓存击穿是巧用指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,解决击穿决方同时读缓存没读到数据,缓存又同时去数据库去取数据,巧用引起数据库压力瞬间增大,解决击穿决方造成过大压力。缓存

巧用lock解决缓存击穿的解决方案 这时由于并发用户特别多

解决方案

1、设置热点数据永远不过期。

2、加互斥锁,互斥锁参考代码如下:

2.1、根据key生成object()

  1. private static object GetMemoryCacheLockObject(string key) 
  2.         {  
  3.             string cacheLockKey = string.Format(MemoryCacheLockObjectFormat, key); 
  4.             lock (CacheObject) 
  5.             {  
  6.                 var lockObject = CacheObject[cacheLockKey]; 
  7.                 if (lockObject == null) 
  8.                 {  
  9.                     // 取得每個 Key專屬的 lock object;若同時有多個 thread要求相同資料,只會(到資料庫)查第一次,剩下的從 cache讀取 
  10.                     lockObject = new object(); 
  11.                     CacheObject.Set( 
  12.                         cacheLockKey, 
  13.                         lockObject, 
  14.                         new System.Runtime.Caching.CacheItemPolicy() 
  15.                         {  
  16.                             AbsoluteExpiration = DateTimeOffset.UtcNow.AddMinutes(10) 
  17.                         } 
  18.                     ); 
  19.                 } 
  20.  
  21.                 return lockObject; 
  22.             } 
  23.         } 

2.2、lock住GetMemoryCacheLockObject(key)

  1. public T Get<T>(string key, Func<T> getDataWork, TimeSpan absoluteExpireTime, bool forceRefresh = false, bool returnCopy = true) where T : class 
  2.         {  
  3.             try 
  4.             {  
  5.                 lock (GetMemoryCacheLockObject(key)) 
  6.                 {  
  7.                     /* 
  8. System.ArgumentNullException: Value cannot be null. 
  9. at System.Threading.Monitor.Enter(Object obj) 
  10. 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 
  11.                      */ 
  12.                     T result = CacheObject[key] as T; 
  13.  
  14.                     if (result != null && forceRefresh) 
  15.                     { // 是否清除Cache,強制重查 
  16.                         result = null; 
  17.                     } 
  18.  
  19.                     if (result == null) 
  20.                     {  
  21.                         //執行取得資料的委派作業 
  22.                         result = getDataWork(); 
  23.  
  24.                         if (result != null) 
  25.                         {  
  26.                             Set(key, result, absoluteExpireTime); 
  27.                         } 
  28.                     } 
  29.  
  30.                     if (returnCopy) 
  31.                     {  
  32.                         //複製一份新的參考 
  33.                         string serialize = JsonConvert.SerializeObject(result); 
  34.                         return JsonConvert.DeserializeObject<T>(serialize); 
  35.                     } 
  36.                     else 
  37.                     {  
  38.                         return result; 
  39.                     } 
  40.                 } 
  41.             } 
  42.             catch 
  43.             {  
  44.                 return getDataWork(); 
  45.             } 
  46.         } 

总结说明

1、缓存中有数据,直接走下述代码就返回结果了

  1. T result = CacheObject[key] as T; 

2、缓存中没有数据,第1个进入的线程,获取锁并从数据库去取数据,没释放锁之前,其他并行进入的线程会等待,再重新去缓存取数据。这样就防止都去数据库重复取数据,重复往缓存中更新数据情况出现。

  1. try 
  2.             {  
  3.                 lock (GetMemoryCacheLockObject(key)) 
  4.                 {  
  5.                     /* 
  6. System.ArgumentNullException: Value cannot be null. 
  7. at System.Threading.Monitor.Enter(Object obj) 
  8. 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 
  9.                      */ 
  10.                     T result = CacheObject[key] as T; 

3、取得每个 Key专有的 lock object;若同时有多个 thread要求相同资料,只会(到数据库)查第一次,剩下的从 cache读取。

  1. string cacheLockKey = string.Format(MemoryCacheLockObjectFormat, key); 
  2.             lock (CacheObject) 
  3.             {  
  4.                 var lockObject = CacheObject[cacheLockKey]; 
  5.                 if (lockObject == null) 
  6.                 {  
  7.                     // 取得每個 Key專屬的 lock object;若同時有多個 thread要求相同資料,只會(到資料庫)查第一次,剩下的從 cache讀取 
  8.                     lockObject = new object(); 

 

 

责任编辑:武晓燕 来源: UP技术控 缓存lock数据

(责任编辑:热点)

    推荐文章
    热点阅读