2021年1月31日星期日

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

背景

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

解决方案

    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();

 









原文转载:http://www.shaoqun.com/a/521244.html

跨境电商:https://www.ikjzd.com/

急速:https://www.ikjzd.com/w/1861

sca:https://www.ikjzd.com/w/2424


背景缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。解决方案1、设置热点数据永远不过期。2、加互斥锁,互斥锁参考代码如下:2.1、根据key生成object()privatestaticobjectGetMemoryCacheLockObject(stringkey){str
kili:kili
洋老板:洋老板
Wish干货:WishPost 联仓项目常见问题解答:Wish干货:WishPost 联仓项目常见问题解答
护肤品怎么入驻速卖通?2020速卖通护肤品行业招商准入资质:护肤品怎么入驻速卖通?2020速卖通护肤品行业招商准入资质
看阿里旗下的Daraz如何在南亚五国乘风破浪 货通南亚:看阿里旗下的Daraz如何在南亚五国乘风破浪 货通南亚

没有评论:

发表评论

跨境电商资讯:外贸宣传平台有哪些(出口的

现在很多做外贸的人都非常关注 外贸企业怎么推广 ,而现在推广的途径和平台有很多,企业如果都做,成本和时间精力是一个问题,而且并不是所有的推广渠道都是有用的。今天云程网络就来为大家盘点几个有效的外贸推广渠道。 一、海外社交媒体营销 Facebook,领英等海外社交媒体营销在近几年得...