如何防止缓存击穿 缓存雪崩,缓存失效带来地问题

Java Web开发之缓存击穿问题Java Web开发之缓存击穿问题神秘大全百家号什么是缓存击穿?我们先来看一段经典的代码,关于缓存使用的查询先从缓存里面获取,缓存如果没有,那么再从数据库查询,并且写入缓存。注意:在实际开发中,我们一般在缓存中,存储的数据结构是JSON字符串。那么 就会有一个问题,假如从数据查询需要1秒时间那么这1秒内请求都会直接到db,缓存被击穿,如果请求特别大的时候,可能数据库就会挂掉。那应该那么解决? 我们一般采用,同步+双重检查的方式请看代码当第一次从缓存获取失败,我们就同步当缓存失效以后第二次进来以及后面的请求,都会从缓存里面获取而第一次请求进来的请求会直接查询数据库会放入缓存中。优化总结:思考1.这里我们锁住的是这个对象,当一个请求获取key为a的值时,锁住了。在未解锁前,那么另一个请求获取key为b的值也是同步阻塞的,想想能不能再减小点锁的粒度?比如使用key来加锁???思考2 在实际开发中,其实缓存的逻辑是差不多,,只是获取数据的方式不一样?想想能不能抽象下?这里我做个代码演示实际调用的时候文章取自朋友的原创!欢迎大家拍砖!本文仅代表作者观点,不代表百度立场。系作者授权百家号发表,未经许可不得转载。神秘大全百家号最近更新:简介:表现宇宙现象,普及科学知识。作者最新文章相关文章7280人阅读
分布式网站(21)
我们在用缓存的时候,不管是Redis或者Memcached,基本上会通用遇到以下三个问题:
缓存穿透缓存并发缓存失效
一、缓存穿透
Paste_Image.png
Paste_Image.png
Paste_Image.png
上面三个图会有什么问题呢?
我们在项目中使用缓存通常都是先检查缓存中是否存在,如果存在直接返回缓存内容,如果不存在就直接查询数据库然后再缓存查询结果返回。这个时候如果我们查询的某一个数据在缓存中一直不存在,就会造成每一次请求都查询DB,这样缓存就失去了意义,在流量大时,可能DB就挂掉了。
那这种问题有什么好办法解决呢?
要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。
有一个比较巧妙的作法是,可以将这个不存在的key预先设定一个值。
比如,&key& , “&&”。
在返回这个&&值的时候,我们的应用就可以认为这是不存在的key,那我们的应用就可以决定是否继续等待继续访问,还是放弃掉这次操作。如果继续等待访问,过一个时间轮询点后,再次请求这个key,如果取到的值不再是&&,则可以认为这时候key有值了,从而避免了透传到数据库,从而把大量的类似请求挡在了缓存之中。
二、缓存并发
有时候如果网站并发访问高,一个缓存如果失效,可能出现多个进程同时查询DB,同时设置缓存的情况,如果并发确实很大,这也可能造成DB压力过大,还有缓存频繁更新的问题。
我现在的想法是对缓存查询加锁,如果KEY不存在,就加锁,然后查DB入缓存,然后解锁;其他进程如果发现有锁就等待,然后等解锁后返回数据或者进入DB查询。
这种情况和刚才说的预先设定值问题有些类似,只不过利用锁的方式,会造成部分请求等待。
三、缓存失效
引起这个问题的主要原因还是高并发的时候,平时我们设定一个缓存的过期时间时,可能有一些会设置1分钟啊,5分钟这些,并发很高时可能会出在某一个时间同时生成了很多的缓存,并且过期时间都一样,这个时候就可能引发一当过期时间到后,这些缓存同时失效,请求全部转发到DB,DB可能会压力过重。
那如何解决这些问题呢?
其中的一个简单方案就时讲缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。
我们讨论的第二个问题时针对同一个缓存,第三个问题时针对很多缓存。
总结来看:
1、缓存穿透:查询一个必然不存在的数据。比如文章表,查询一个不存在的id,每次都会访问DB,如果有人恶意破坏,很可能直接对DB造成影响。
2、缓存失效:如果缓存集中在一段时间内失效,DB的压力凸显。这个没有完美解决办法,但可以分析用户行为,尽量让失效时间点均匀分布。
当发生大量的缓存穿透,例如对某个失效的缓存的大并发访问就造成了缓存雪崩。
四、大家提问汇总
1、问题1:
如何解决DB和缓存一致性问题?
答:当修改了数据库后,有没有及时修改缓存。这种问题,以前有过实践,修改数据库成功,而修改缓存失败的情况,最主要就是缓存服务器挂了。而因为网络问题引起的没有及时更新,可以通过重试机制来解决。而缓存服务器挂了,请求首先自然也就无法到达,从而直接访问到数据库。那么我们在修改数据库后,无法修改缓存,这时候可以将这条数据放到数据库中,同时启动一个异步任务定时去检测缓存服务器是否连接成功,一旦连接成功则从数据库中按顺序取出修改数据,依次进行缓存最新值的修改。
2、问题2:
问下缓存穿透那块!例如,一个用户查询文章,通过ID查询,按照之前说的,是将缓存的KEY预先设置一个值,,如果通过ID插过来,发现是预先设定的一个值,比如说是“&&”,那之后的继续等待访问是什么意思,这个ID什么时候会真正被附上用户所需要的值呢?
答:我刚说的主要是咱们常用的后面配置,前台获取的场景。前台无法获取相应的key,则等待,或者放弃。当在后台配置界面上配置了相关key和value之后,那么以前的key &&也自然会被替换掉。你说的那种情况,自然也应该会有一个进程会在某一个时刻,在缓存中设置这个ID,再有新的请求到达的时候,就会获取到最新的ID和value。
3、问题3:
其实用redis的话,那天看到一个不错的例子,双key,有一个当时生成的一个附属key来标识数据修改到期时间,然后快到的时候去重新加载数据,如果觉得key多可以把结束时间放到主key中,附属key起到锁的功能。
答:这种方案,之前我们实践过。这种方案会产生双份数据,而且需要同时控制附属key与key之间的关系,操作上有一定复杂度。
4、问题4:
多级缓存是什么概念呢?
答:多级缓存就像我今天之前给大家发的文章里面提到了,将ehcache与redis做二级缓存,就像我之前写的文章
提到过的。但同样会存在一致性问题,如果我们需要强一致性的话,缓存与数据库同步是会存在时间差的,所以我们在具体开发的过程中,一定要根据场景来具体分析,二级缓存更多的解决是,缓存穿透与程序的健壮性,当集中式缓存出现问题的时候,我们的应用能够继续运行。
文/小程故事多(简书作者)
原文链接:http://www.jianshu.com/p/d
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。博客分类:
缓存一般作为RDS的前置组件,将常用的资源缓存,用来减少RDS的读取压力,也是诸多系统常用的一种方案,如果允许访问缓存失败直接访问数据库,然后再将数据回写到缓存中,那么就会存在缓存击穿的问题,
缓存击穿:缓存中的数据未被命中,进而请求直接对数据库进行查询,当大量的类似查询瞬间出现,就会出现数据库的压力爆炸甚至引起数据库的雪崩,本质就是一种缓存失效引发的极端问题
如何应对这种情况?
在很多面试过程中碰到这样的问题,给出答案:不给缓存击穿的机会
首先不允许跨过缓存直接访问数据库,在缓存中及认为数据可以被访问,否则则认为访问的数据不存在,
接下来就是RDS和缓存的同步问题,保证数据最终会呈现给用户,但是有延迟,功能的延迟和系统雪崩的风险选择,个人比较倾向于后者,
这种方案将数据的查询完全依赖缓存,一旦缓存挂掉,基本系统也就over了,这就依赖缓存的高可用部署了,采用集群或者多集群的方式,提高系统的可用性,剩下的就是和RDS一样的问题,比如防攻击,数据切片等
另外还有一种方案,加锁的方式,对于同一个key进行枷锁,当key 不命中的时候,需要去数据库中去查询然后回写到缓存中,查询已经回写的操作进行加锁,粗暴一点 可以用synchronized直接加锁,最坏的情况,jvm中,某个key的请求的请求 全部block,另外可以用分布式锁的方案,当发现key不命中时向redis中添加一个lock_key,添加方式使用setnx指令,这样同一个key的请求只有一个成功,设置成功的请求,进行查询回写操作,设置失败的请求,建议直接进行返回,不要等待,比较一个服务器的连接数是有限制的,如果太多请求等待的话 会影响其他的正常业务
浏览: 2985 次
来自: 上海
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'Java Web开发之缓存击穿问题_【快资讯】
Java Web开发之缓存击穿问题
什么是缓存击穿?我们先来看一段经典的代码,关于缓存使用的查询先从缓存里面获取,缓存如果没有,那么再从数据库查询,并且写入缓存。注意:在实际开发中,我们一般在缓存中,存储的数据结构是JSON字符串。那么 就会有一个问题,假如从数据查询需要1秒时间那么这1秒内请求都会直接到db,缓存被击穿,如果请求特别大的时候,可能数据库就会挂掉。那应该那么解决? 我们一般采用,同步+双重检查的方式请看代码当第一次从缓存获取失败,我们就同步当缓存失效以后第二次进来以及后面的请求,都会从缓存里面获取而第一次请求进来的请求会直接查询数据库会放入缓存中。优化总结:思考1.这里我们锁住的是这个对象,当一个请求获取key为a的值时,锁住了。在未解锁前,那么另一个请求获取key为b的值也是同步阻塞的,想想能不能再减小点锁的粒度?比如使用key来加锁???思考2 在实际开发中,其实缓存的逻辑是差不多,,只是获取数据的方式不一样?想想能不能抽象下?这里我做个代码演示实际调用的时候文章取自朋友的原创!欢迎大家拍砖!更多频道内容在这里查看
爱奇艺用户将能永久保存播放记录
过滤短视频
暂无长视频(电视剧、纪录片、动漫、综艺、电影)播放记录,
按住视频可进行拖动
&正在加载...
收藏成功,可进入
查看所有收藏列表
当前浏览器仅支持手动复制代码
视频地址:
flash地址:
html代码:
通用代码:
通用代码可同时支持电脑和移动设备的分享播放
用爱奇艺APP或微信扫一扫,在手机上继续观看
当前播放时间:
一键下载至手机
限爱奇艺安卓6.0以上版本
使用微信扫一扫,扫描左侧二维码,下载爱奇艺移动APP
其他安装方式:手机浏览器输入短链接http://71.am/udn
下载安装包到本机:
设备搜寻中...
请确保您要连接的设备(仅限安卓)登录了同一爱奇艺账号 且安装并开启不低于V6.0以上版本的爱奇艺客户端
连接失败!
请确保您要连接的设备(仅限安卓)登录了同一爱奇艺账号 且安装并开启不低于V6.0以上版本的爱奇艺客户端
部安卓(Android)设备,请点击进行选择
请您在手机端下载爱奇艺移动APP(仅支持安卓客户端)
使用微信扫一扫,下载爱奇艺移动APP
其他安装方式:手机浏览器输入短链接http://71.am/udn
下载安装包到本机:
爱奇艺云推送
请您在手机端登录爱奇艺移动APP(仅支持安卓客户端)
使用微信扫一扫,下载爱奇艺移动APP
180秒后更新
打开爱奇艺移动APP,点击“我的-扫一扫”,扫描左侧二维码进行登录
没有安装爱奇艺视频最新客户端?
轻松解决缓存击穿
正在检测客户端...
您尚未安装客户端,正在为您下载...安装完成后点击按钮即可下载
30秒后自动关闭
轻松解决缓存击穿">轻松解决缓存击穿
请选择打赏金额:
播放量12.7万
播放量数据:快去看看谁在和你一起看视频吧~
更多数据:
Copyright (C) 2018 & All Rights Reserved
您使用浏览器不支持直接复制的功能,建议您使用Ctrl+C或右键全选进行地址复制
正在为您下载爱奇艺客户端安装后即可快速下载海量视频
正在为您下载爱奇艺客户端安装后即可免费观看1080P视频
&li data-elem="tabtitle" data-seq="{{seq}}"& &a href="javascript:void(0);"& &span>{{start}}-{{end}}&/span& &/a& &/li&
&li data-downloadSelect-elem="item" data-downloadSelect-selected="false" data-downloadSelect-tvid="{{tvid}}"& &a href="javascript:void(0);"&{{pd}}&/a&
选择您要下载的《
色情低俗内容
血腥暴力内容
广告或欺诈内容
侵犯了我的权力
还可以输入
您使用浏览器不支持直接复制的功能,建议您使用Ctrl+C或右键全选进行地址复制}

我要回帖

更多关于 防止缓存击穿 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信