redis击穿,穿透,雪崩以及解决方案
1 击穿: 指的是单个key在缓存中查不到,去数据库查询,这样如果数据量不大或者并发不大的话是没有什么问题的。
如果数据库数据量大并且是高并发的情况下那么就可能会造成数据库压力过大而崩溃
注意: 这里指的是单个key发生高并发!!!
解决方案:
1) 通过synchronized+双重检查机制:某个key只让一个线程查询,阻塞其它线程
在同步块中,继续判断检查,保证不存在,才去查DB。
例如:
private static volaite Object lockHelp=new Object();
public String getValue(String key){
String value=redis.get(key,String.class);
if(value=="null"||value==null||StringUtils.isBlank(value){
synchronized(lockHelp){
value=redis.get(key,String.class);
if(value=="null"||value==null||StringUtils.isBlank(value){
value=db.query(key);
redis.set(key,value,1000);
}
}
}
return value;
}
缺点: 会阻塞其它线程
2) 设置value永不过期
这种方式可以说是最可靠的,最安全的但是占空间,内存消耗大,并且不能保持数据最新 这个需要根据具体的业务逻辑来做
个人觉得如果要保持数据最新不放这么试试,仅供参考:
起个定时任务或者利用TimerTask 做定时,每个一段时间多这些值进行数据库查询更新一次缓存,当然前提时不会给数据库造成压力过大(这个很重要)
3) 使用互斥锁(mutex key)
业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。
SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果。在redis2.6.1之前版本未实现setnx的过期时间,所以这里给出两种版本代码参考:
public String get(key) {
String value = redis.get(key);
if (value == null) { //代表缓存值过期
//设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能load db
if (redis.setnx(key_mutex, 1, 3 * 60) == 1) { //代表设置成功
value = db.get(key);
redis.set(key, value, expire_secs);
redis.del(key_mutex);
return value;
} else { //这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可
sleep(10);
get(key); //重试
}
} else {
return value;
}
}
缺点:
1. 代码复杂度增大
2. 存在死锁的风险
3. 存在线程池阻塞的风险
2 雪崩
雪崩指的是多个key查询并且出现高并发,缓存中失效或者查不到,然后都去db查询,从而导致db压力突然飙升,从而崩溃。
出现原因: 1 key同时失效
2 redis本身崩溃了
方案:
- 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。(跟击穿的第一个方案类似,但是这样是避免不了其它key去查数据库,只能减少查询的次数)
- 可以通过缓存reload机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存
- 不同的key,设置不同的过期时间,具体值可以根据业务决定,让缓存失效的时间点尽量均匀
- 做二级缓存,或者双缓存策略。A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期。(这种方式复杂点)
3 穿透
一般是出现这种情况是因为恶意频繁查询才会对系统造成很大的问题: key缓存并且数据库不存在,所以每次查询都会查询数据库从而导致数据库崩溃。
解决方案:
1) 使用布隆过滤器: 热点数据等场景(具体看使用场景)
布隆过滤器是什么?
布隆过滤器可以理解为一个不怎么精确的 set 结构,当你使用它的 contains 方法判断某个对象是否存在时,它可能会误判。但是布隆过滤器也不是特别不精确,只要参数设置的合理,它的精确度可以控制的相对足够精确,只会有小小的误判概率。
当布隆过滤器说某个值存在时,这个值可能不存在;当它说不存在时,那就肯定不存在。打个比方,当它说不认识你时,肯定就不认识;当它说见过你时,可能根本就没见过面,不过因为你的脸跟它认识的人中某脸比较相似 (某些熟脸的系数组合),所以误判以前见过你。
缺点: 1 会存在一定的误判率
2 对新增加的数据无法进行布隆过滤
3 数据的key不会频繁的更改
google 的 gauva 中有布隆过滤的实现
BloomFilter的关键在于hash算法的设定和bit数组的大小确定,通过权衡得到一个错误概率可以接受的结果。
我们设置的容错率越小那么过滤函数也就多,分配的空间也就越大(存放bits),那么误判率也就越小。
2 将击透的key缓存起来,但是时间不能太长,下次进来是直接返回不存在,但是这种情况无法过滤掉动态的key,就是说每次请求进来都是不同额key,这样还是会造成这个问题
redis击穿,穿透,雪崩以及解决方案相关推荐
- 你需要知道的缓存击穿/穿透/雪崩
目录 缓存击穿/穿透/雪崩 Intro 缓存击穿 缓存穿透 缓存雪崩 Reference Contact 缓存击穿/穿透/雪崩 Intro 使用缓存需要了解几个缓存问题,缓存击穿.缓存穿透以及缓存雪崩 ...
- 缓存击穿/穿透/雪崩
缓存击穿/穿透/雪崩 Intro 使用缓存需要了解几个缓存问题,缓存击穿.缓存穿透以及缓存雪崩,需要了解它们产生的原因以及怎么避免,尤其是当你打算设计自己的缓存框架的时候需要考虑如何处理这些问题. 缓 ...
- Redis缓存穿透问题及解决方案
Redis缓存穿透问题及解决方案 参考文章: (1)Redis缓存穿透问题及解决方案 (2)https://www.cnblogs.com/lingyejun/p/10087135.html 备忘一下 ...
- redis击穿、雪崩、穿透解决方案
Redis击穿 redis缓存击穿是指某一个非常热点的key(即在客户端搜索的比较多的关键字)突然失效了,这时从客户端发送的大量的请求在redis里找不到这个key,就会去数据里找,最终导致数据库压力 ...
- Redis击穿、雪崩、穿透场景描述与解决方案
1.击穿 (1)场景描述 缓存中的某个key由于过期了,并且前端数据出现高并发(一定要有高并发)请求该key(实际上概率很低),导致瞬间都打在数据库上. (2)解决方案 使用redis的setnx(表 ...
- 面试常问:redis缓存击穿/穿透/雪崩
1. 讲个故事 一个人去门店买联想电脑,线下门店没有货了,于是店员给厂家打电话问问有没有货,厂家发现也没货了,这个人就走了.过了一会另一个人也要来买联想电脑,然后店员又打电话问了一次厂家,如此反复.这 ...
- redis——缓存击穿/穿透/雪崩
缓存穿透 一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就去后端系统查找(比如DB). 一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力.这就叫 ...
- Redis数据读取(缓存击穿,穿透,雪崩)
内容文件参考"付费专栏"可领取.专栏购买者提供本内容"永久答疑和远程协助"服务.一诺千金! N.1 缓存处理流程 1)前台请求,后台先从缓存中取数据,取到直接返 ...
- 缓存击穿和雪崩常用解决方案
目录 1 抢红包排行查询 2 击穿现象分析 3 击穿解决方案 3.1 定时器 3.2 多级缓存 3.3 分布式锁 3.4 队列术 4 缓存雪崩介绍 1 抢红包排行查询 上面案例我们实现了某个用户抢红包 ...
- redis缓存穿透问题及解决方案代码实现
1.定义及解决方案 缓存穿透 :缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库. 常见的解决方案有两种: 缓存空对象 优点:实现简单,维护方便 缺 ...
最新文章
- clisp语言中的包
- lisp 任意点 曲线距离_奇怪的知识增加了:把标准形式的双曲线旋转来解决问题...
- Vue——定义全局工具类
- Linux终端操作MySQL常用命令
- mac 删除php56 安装php72,mac php56升级php70
- 抽象类可以生成自己的对象吗_大理石可以自己抛光吗?大理石自己抛光方法解答...
- Centos7上kvm虚拟化自定义NAT网络
- textarea 字体限制,超出部分不显示并及时显示还剩字体个数
- 好吧,你说简单就简单,但简单的事,不要变成本能,要常思常变
- linux下进程号,Linux下C++获取进程号
- 专为前端开发者准备的 15 款优秀的 Sublime Text 插件
- python k线形态识别_python量化金融系列-K线分析、及形态捕捉
- 一个IT工薪族的7年奋斗成果:天鸟之路,天鸟有财,天鸟有度
- 5个APP自动化测试辅助定位工具,你用过几个?
- mysql按时间段统计_mysql按照时间段内 每天统计
- 量化分析入门7:获取多支股票的收盘价
- 【单片机笔记】运放电流检测实用电路
- MFC 获取系统时间及比较
- C++ STL?看这篇就够啦。草履虫都能学会的STL教程!
- Keytool命令详解(好文章!详细设置一些参数比如过期时间等)
热门文章
- postman 9.16 打不开怎么办
- Oracle用OEM和命令行方式创建用户及表空间
- 团队项目-初步分工与计划安排
- html多行多列的表单,如何制作多行多列的表格
- 学习编程前需要知道什么?
- uniapp中H5网页和打包app分别生成二维码
- excel 画散点图 怎么设置图片的分辨率_Slynyrd像素画教程:像素画基础教程
- [h5py] 解决ImportError: libhdf5.so.103: cannot open shared object file: No such file or directory
- 5.42如何高效的学习开源项目
- tf-faster-rcnn训练报错: Loaded runtime CuDNN library: 7.0.5 but source was compiled with: 7.1.4.r-rcn