背景

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

解决方案

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

巧用lock解决缓存击穿的解决方案相关推荐

  1. php cachelock,巧用lock解决缓存击穿的解决方案

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

  2. Spring Cache使用Redisson分布式锁解决缓存击穿问题

    文章目录 1 什么是缓存击穿 2 为什么要使用分布式锁 3 什么是Redisson 4 Spring Boot集成Redisson 4.1 添加maven依赖 4.2 配置yml 4.3 配置Redi ...

  3. 分布式之一行代码解决缓存击穿问题

    开局一张图,内容全靠编- 我只能说一言难尽--我只能说,感情影响了一名剑客拔剑的速度,就是这样! 引言 今天,重新回顾一下缓存击穿这个问题! 之所以写这个文章呢,因为目前网上流传的文章落地性太差(什么 ...

  4. 使用BloomFilter布隆过滤器解决缓存击穿、垃圾邮件识别、集合判重

    Bloom Filter是一个占用空间很小.效率很高的随机数据结构,它由一个bit数组和一组Hash算法构成.可用于判断一个元素是否在一个集合中,查询效率很高(1-N,最优能逼近于1). 在很多场景下 ...

  5. Redis( 缓存篇 ==> 互斥锁解决缓存击穿

    我们可以在查询缓存未命中的时候添加一个互斥锁.这样一来,在面对高并发的情况下,只有第一个进来的线程才可以拿到锁然后操作数据库,待操作结束后释放锁,未拿到锁的用户则等待一段时间重新查询缓存,直到缓存重建 ...

  6. 缓存穿透与击穿问题解决方案

    在互联网场景中缓存系统是一个重要系统,为了防止流量频繁访问数据库,一般会在数据库层前设置一道缓存层作为保护. 缓存是一个广义的概念,核心要义是将数据存放在离用户更近的地方,或者是将数据存放在访问更快的 ...

  7. Redis缓存击穿和缓存雪崩、缓存穿透以及对应的解决方案

    目录 缓存击穿 缓存击穿的解决方案 缓存雪崩 缓存雪崩的解决方案 缓存穿透 布隆过滤器 缓存击穿 一般我们会对缓存的key设置过期时间,在高并发下,如果在某一时刻这个key刚好过期,此时持续的大并发请 ...

  8. Redis 缓存击穿,缓存穿透,缓存雪崩原因+解决方案

    一.前言 在我们日常的开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问题,可是一旦涉及大数据量的需求,比如一些商品抢购的情景,或者是 ...

  9. java如何解决缓存问题_4种常见的缓存问题及解决方案详解

    前言 使用缓存可以缓解大流量压力,显著提高程序的性能.我们在使用缓存系统时,尤其是大并发情况下,经常会遇到一些"疑难杂症".本文总结了一些使用缓存时常见的问题及解决方案,以后在遇到 ...

最新文章

  1. 深度神经网络控制的巡线智能车
  2. please get a license from www.texturepacker.com
  3. PHP判断iPhone、iPad、Android、PC设备的方法
  4. 信息系统项目管理师-信息文档与配置管理考点笔记
  5. 使用SWig出现调用异常的情况
  6. Java基础教程:面向对象编程[2]
  7. python locust 性能测试:HOOKS钩子方法
  8. mac+nginx+php70+mysql环境搭建
  9. vue中Component错误
  10. python中post()方法在获取获取必应网站翻译结果中的应用
  11. 百旺智能编码_百旺税控盘如何增加商品编码?
  12. 嗅探工具 --- wireshark、tcpdump、dsniff、ettercap、bettercap、netsniff-ng
  13. LibreELEC(kodi)安装
  14. 三星矫情,重温Galaxy S5发布会收买人心
  15. 格灵深瞳:人脸识别最新进展以及工业级大规模人脸识别实践探讨 | 公开课笔记...
  16. Metasploit(一)
  17. android adb shell杀进程
  18. 关于系统复杂性的一句箴言
  19. Android移动开发:第一章Android系统概述
  20. 九寨沟7.0级大地震,希望大家都能够平安

热门文章

  1. 基于.NET2.0的System.Net.Mail发送邮件Demo
  2. 汉三水属国(北地属国、安定属国)
  3. [中文版] 可视化 CSS References 文档
  4. HDU 5238 Calculator 线段树 中国剩余定理
  5. 新增功能!Trello个人应用程序登陆 Microsoft Teams
  6. 如何在Windows 8.1中获取Windows 10样式的开始菜单
  7. linux guard什么进程,使用linux系统性能监控工具KSysguard监控远端主机介绍
  8. MySQL设置从库只读模式
  9. 2018暑假集训---递推递归----一只小蜜蜂hdu2044
  10. Android Studio3.0简介