巧用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();
巧用lock解决缓存击穿的解决方案相关推荐
- php cachelock,巧用lock解决缓存击穿的解决方案
背景 缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力. 解决方案 1.设置热 ...
- Spring Cache使用Redisson分布式锁解决缓存击穿问题
文章目录 1 什么是缓存击穿 2 为什么要使用分布式锁 3 什么是Redisson 4 Spring Boot集成Redisson 4.1 添加maven依赖 4.2 配置yml 4.3 配置Redi ...
- 分布式之一行代码解决缓存击穿问题
开局一张图,内容全靠编- 我只能说一言难尽--我只能说,感情影响了一名剑客拔剑的速度,就是这样! 引言 今天,重新回顾一下缓存击穿这个问题! 之所以写这个文章呢,因为目前网上流传的文章落地性太差(什么 ...
- 使用BloomFilter布隆过滤器解决缓存击穿、垃圾邮件识别、集合判重
Bloom Filter是一个占用空间很小.效率很高的随机数据结构,它由一个bit数组和一组Hash算法构成.可用于判断一个元素是否在一个集合中,查询效率很高(1-N,最优能逼近于1). 在很多场景下 ...
- Redis( 缓存篇 ==> 互斥锁解决缓存击穿
我们可以在查询缓存未命中的时候添加一个互斥锁.这样一来,在面对高并发的情况下,只有第一个进来的线程才可以拿到锁然后操作数据库,待操作结束后释放锁,未拿到锁的用户则等待一段时间重新查询缓存,直到缓存重建 ...
- 缓存穿透与击穿问题解决方案
在互联网场景中缓存系统是一个重要系统,为了防止流量频繁访问数据库,一般会在数据库层前设置一道缓存层作为保护. 缓存是一个广义的概念,核心要义是将数据存放在离用户更近的地方,或者是将数据存放在访问更快的 ...
- Redis缓存击穿和缓存雪崩、缓存穿透以及对应的解决方案
目录 缓存击穿 缓存击穿的解决方案 缓存雪崩 缓存雪崩的解决方案 缓存穿透 布隆过滤器 缓存击穿 一般我们会对缓存的key设置过期时间,在高并发下,如果在某一时刻这个key刚好过期,此时持续的大并发请 ...
- Redis 缓存击穿,缓存穿透,缓存雪崩原因+解决方案
一.前言 在我们日常的开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问题,可是一旦涉及大数据量的需求,比如一些商品抢购的情景,或者是 ...
- java如何解决缓存问题_4种常见的缓存问题及解决方案详解
前言 使用缓存可以缓解大流量压力,显著提高程序的性能.我们在使用缓存系统时,尤其是大并发情况下,经常会遇到一些"疑难杂症".本文总结了一些使用缓存时常见的问题及解决方案,以后在遇到 ...
最新文章
- 深度神经网络控制的巡线智能车
- please get a license from www.texturepacker.com
- PHP判断iPhone、iPad、Android、PC设备的方法
- 信息系统项目管理师-信息文档与配置管理考点笔记
- 使用SWig出现调用异常的情况
- Java基础教程:面向对象编程[2]
- python locust 性能测试:HOOKS钩子方法
- mac+nginx+php70+mysql环境搭建
- vue中Component错误
- python中post()方法在获取获取必应网站翻译结果中的应用
- 百旺智能编码_百旺税控盘如何增加商品编码?
- 嗅探工具 --- wireshark、tcpdump、dsniff、ettercap、bettercap、netsniff-ng
- LibreELEC(kodi)安装
- 三星矫情,重温Galaxy S5发布会收买人心
- 格灵深瞳:人脸识别最新进展以及工业级大规模人脸识别实践探讨 | 公开课笔记...
- Metasploit(一)
- android adb shell杀进程
- 关于系统复杂性的一句箴言
- Android移动开发:第一章Android系统概述
- 九寨沟7.0级大地震,希望大家都能够平安
热门文章
- 基于.NET2.0的System.Net.Mail发送邮件Demo
- 汉三水属国(北地属国、安定属国)
- [中文版] 可视化 CSS References 文档
- HDU 5238 Calculator 线段树 中国剩余定理
- 新增功能!Trello个人应用程序登陆 Microsoft Teams
- 如何在Windows 8.1中获取Windows 10样式的开始菜单
- linux guard什么进程,使用linux系统性能监控工具KSysguard监控远端主机介绍
- MySQL设置从库只读模式
- 2018暑假集训---递推递归----一只小蜜蜂hdu2044
- Android Studio3.0简介