当前位置: 首页 > 编程日记 > 正文

缓存穿透、并发和失效的解决方案

我们在用缓存的时候,不管是Redis或者Memcached,基本上会通用遇到以下三个问题:

  • 缓存穿透

  • 缓存并发

  • 缓存失效

缓存穿透


注:上面三个图会有什么问题呢?

我们在项目中使用缓存通常都是先检查缓存中是否存在,如果存在直接返回缓存内容,如果不存在就直接查询数据库然后再缓存查询结果返回。这个时候如果我们查询的某一个数据在缓存中一直不存在,就会造成每一次请求都查询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的压力凸显。这个没有完美解决办法,但可以分析用户行为,尽量让失效时间点均匀分布。

当发生大量的缓存穿透,例如对某个失效的缓存的大并发访问就造成了缓存雪崩。

精彩问答

问题:如何解决DB和缓存一致性问题?

当修改了数据库后,有没有及时修改缓存。这种问题,以前有过实践,修改数据库成功,而修改缓存失败的情况,最主要就是缓存服务器挂了。而因为网络问题引起的没有及时更新,可以通过重试机制来解决。而缓存服务器挂了,请求首先自然也就无法到达,从而直接访问到数据库。那么我们在修改数据库后,无法修改缓存,这时候可以将这条数据放到数据库中,同时启动一个异步任务定时去检测缓存服务器是否连接成功,一旦连接成功则从数据库中按顺序取出修改数据,依次进行缓存最新值的修改。

问题:问下缓存穿透那块!例如,一个用户查询文章,通过ID查询,按照之前说的,是将缓存的KEY预先设置一个值,,如果通过ID插过来,发现是预先设定的一个值,比如说是“&&”,那之后的继续等待访问是什么意思,这个ID什么时候会真正被附上用户所需要的值呢?

我刚说的主要是咱们常用的后面配置,前台获取的场景。前台无法获取相应的key,则等待,或者放弃。当在后台配置界面上配置了相关key和value之后,那么以前的key &&也自然会被替换掉。你说的那种情况,自然也应该会有一个进程会在某一个时刻,在缓存中设置这个ID,再有新的请求到达的时候,就会获取到最新的ID和value。

问题:其实用Redis的话,那天看到一个不错的例子,双key,有一个当时生成的一个附属key来标识数据修改到期时间,然后快到的时候去重新加载数据,如果觉得key多可以把结束时间放到主key中,附属key起到锁的功能。

这种方案,之前我们实践过。这种方案会产生双份数据,而且需要同时控制附属key与key之间的关系,操作上有一定复杂度。

问题:多级缓存是什么概念呢?

多级缓存就像我今天之前给大家发的文章里面提到了,将Ehcache与Redis做二级缓存,就像我之前写的文章 http://www.jianshu.com/p/2cd6ad416a5a 提到过的。但同样会存在一致性问题,如果我们需要强一致性的话,缓存与数据库同步是会存在时间差的,所以我们在具体开发的过程中,一定要根据场景来具体分析,二级缓存更多的解决是,缓存穿透与程序的健壮性,当集中式缓存出现问题的时候,我们的应用能够继续运行。

相关文章:

CentOS 7 命令

Centos 7 目录说明 / / 是根目录。 /bin 软连接到 /usr/bin。可以理解/bin 是 /usr/bin 的快捷方式。 /lib 软连接到 /usr/lib。 /lib64 软连接到 /usr/lib64。 /sbin 软连接到 /usr/sbin。 /usr软件安装位置 /usr/bin 为系统命令所在目录。 /usr/local 为安装程序所在目录。 /…

算法基础知识科普:8大搜索算法之AVL树(上)

前段时间介绍了二叉搜索树(BST),我们知道这种搜索结构存在的弊端是对输入序列存在强依赖,若输入序列基本有序,则BST近似退化为链表。这样就会大大降低搜索的效率。AVL树以及Red-Black树就是为了解决这个问题&#xff0…

GARFIELD@04-09-2005

a technical facto 转载于:https://www.cnblogs.com/rexhost/archive/2005/04/09/134701.html

Vue.js学习系列(四十二)-- Vue.js组件

2019独角兽企业重金招聘Python工程师标准>>> 组件(Component)是Vue.js最强大的功能之一。组件可以扩展HTML元素,封装可重用的代码。组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任 意类型的应用的界面都…

java sqlite使用小记

2019独角兽企业重金招聘Python工程师标准>>> Sqlite教程: http://www.runoob.com/sqlite/sqlite-tutorial.html 加载sqlite jdbc驱动: static{ try { Class.forName("org.sqlite.JDBC"); } catch (ClassNotFoundException e) { e.p…

算法基础知识科普:8大搜索算法之AVL树(中)

昨天我们介绍了平衡二叉树的基本概念,通过平衡因子来控制左右子树的深度,使得整个二叉搜索树始终保持平衡状态。这个算法的核心在于当平衡因子超过范围,如何通过旋转的方式来使二叉搜索树保持平衡,以及平衡后对应结点平衡因子如何…

Linux登录那点事

跨平台系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#linux 我们登录linux的时候基本上不太关注上面的这个提示,其实这个还是有点文章的 简单解释一下: 上一次dnt用户登录的时间,以及终端是tty1 知识普及:…

解决了一个遗留的Portlet奇怪问题

在做Portlet的时候碰到一个奇怪的问题,使用Java应用程序来进行RFT传输好好的,但在Pluto下,同样的一段程序却不行,提示:No client transport named https found!  搜索GT官网的maillist,发现有人提到是AXI…

Python 程序如何高效地调试?

Python在debug方面的支持还是不错的,在明确代码意义的情况下,通过log、print和assert分析错误原因,配合单元测试可以很高效。然而,实际工作中大量代码很可能出自他人之手,这种情况下,使用debugger就显得更加…

selenium中javascript调试

之前写了使用js输入长文件的文章,有同事在使用时,发现竟然无法输入,也不知道是什么原因,且用的还是id方式。 在参考网文后,才发现是js写的有问题,现总结一下 javascript调试,在firefox中就自带有…

算法基础知识科普:8大搜索算法之AVL树(下)

昨天我们介绍了在进行结点插入时,若左子树深度超过右子树深度两层则进行右旋来保持平衡。今天继续介绍,若右子树深度超过左子树深度两层时的左旋操作,以及删除结点后平衡因子的变更问题。 这些都掌握后,基本上对AVL就有一个很全面…

《代码敲不队》第八次团队作业:Alpha冲刺 第二天

项目内容这个作业属于哪个课程任课教师博客主页链接这个作业的要求在哪里作业链接地址团队名称代码敲不队作业学习目标掌握软件编码实现的工程要求。团队项目github仓库地址链接 GitHub 第二天 日期:2019/6/16 今日完成任务情况以及遇到的问题 针对设计好的数据库&a…

我的.net程序为何不能执行?

今天早上习惯性的打开公司内部的网站。不料却发现我在输入地址后,系统竟会弹出一个对话框要求输入用户名和密码。想了想后,输入了AD的密码,就可以进入了网站。不经意间我又发现所有的asp.net的页面都不能打开,而asp的页面却一点问…

利用MySQL触发器实现check和assertion

MySQL虽然输入check语句不会报错,但是实际上并没有check的功能。但是MySQL 依然可以利用触发器来实现相应功能。 本文将根据两个例子简要阐述MySQL实现check和assertion的思路。 MySQL触发器 官方文档 MySQL Signal 官方文档 注意 signal异常处理功能在MySQL5.5版本…

算法基础知识科普:8大搜索算法之红黑树(上)

平衡二叉树(AVL)是一种特殊的二叉搜索树(BST),即每个结点的值都大于其左子树且小于其右子树的值(若存在),并通过引入平衡因子的概念来保持树的平衡。平衡二叉树算法的重点是在插入、…

Java Web学习总结(17)——JSP属性范围

2019独角兽企业重金招聘Python工程师标准>>> 所谓的属性范围就是一个属性设置之后,可以经过多少个其他页面后仍然可以访问的保存范围。 一、JSP属性范围 JSP中提供了四种属性范围,四种属性范围分别指以下四种: 当前页:…

为什么不提供离线Blog管理工具呢?

网络Blog现在是到处开花, 好像全世界的网民都开始写Blog了. 但因为Web的HTTP无状态协议, 网站本身都自己设置有session过期时间. 如果写的Blog文字多,时间一长用户登录状态就没了,当你提交你的文字时系统会出错,结果你回来时,你辛辛苦苦写的长长的文字都没了, 你是不是很气愤?…

javascript a 标签打开相对路径,绝对路径

<a>标签中的href中&#xff0c;如果你写一个路径默认是以相对路径打开的&#xff0c;加上"http://" 消息头那就可以打开绝对路径 html&#xff1a; <a hrefjavascript:void(0); target_blank onclickCommon.openUrl(" rowObject.baiduPanUrl ")…

算法基础知识科普:8大搜索算法之红黑树(中)

红黑树也是一种特殊形式的二叉搜索树&#xff0c;通过结点的颜色以及三条规则来保证二叉搜索树的平衡。规则1&#xff1a;根结点的颜色是黑色&#xff0c;规则2&#xff1a;叶子结点到根结点路径上遇到的黑色结点数目相同&#xff0c;规则3&#xff1a;叶子结点到根结点路径上无…

Java基础学习总结(3)——抽象类

2019独角兽企业重金招聘Python工程师标准>>> 一、抽象类介绍 下面通过一下的小程序深入理解抽象类 因此在类Animal里面只需要定义这个enjoy()方法就可以了&#xff0c;使用abstract关键字把enjoy()方法定义成一个抽象方法&#xff0c;定义如下&#xff1a;public ab…

Knuth(佩服的一塌糊涂)

Donald Knuth自传的开头这样写道&#xff1a;“Donald Knuth真的只是一个人么&#xff1f;”(我觉得不是&#xff0c;^_^)作为世界顶级计算机科学家之一&#xff0c;Knuth教授已经完成了编译程序、属性文法和运算法则的前沿研究&#xff0c;并编著完成了已在程序设计领域中具有…

编程基础知识科普:C#中的问号运算符

C#是一门非常性感的语言&#xff0c;时不时冒出一些语法糖来满足大家的需求&#xff0c;问号运算符就是其中的一种。我们知道基础数据类型的默认值都是基础数据类型的&#xff0c;如int为0&#xff0c;double为0.0&#xff0c;bool为false等等&#xff0c;而引用类型的默认值为…

Listener监听器之HttpSessionListener

编写一个OnlineUserListener。 package anni; import java.util.List; import javax.servlet.ServletContext; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionListener; import javax.servlet.http.HttpSessionEvent;public class OnlineUserL…

ActiveMQ快速入门

2019独角兽企业重金招聘Python工程师标准>>> 1.下载ActiveMQ 去官方网站下载&#xff1a;http://activemq.apache.org/ 2.运行ActiveMQ 解压缩apache-activemq-5.5.1-bin.zip&#xff0c;然后双击apache-activemq-5.5.1\bin\activemq.bat运行ActiveMQ程序。 启动Act…

企业为什么要使用基于Docker的PaaS/CaaS平台

作者&#xff1a;精灵云 前言早在十多年前国内外的一些大厂就开始投入研发和使用容器技术&#xff0c;比如Google&#xff0c;对他们来说&#xff0c;使用容器能够充分利用计算资源节省硬件成本。而这几年——众所周知——真正把容器技术发扬光大的是Docker。Docker的slogan“B…

算法基础知识科普:8大搜索算法之红黑树(下)

这是介绍红黑树的最后一部分&#xff0c;令y为要删除结点&#xff0c;n为要删除结点的子结点&#xff08;子结点最多有1个&#xff09;&#xff0c;w为y的兄弟结点&#xff0c;删除操作的重点是使红黑树删除结点并通过调整后仍满足自身是搜索二叉树和设定的三点规则。删除操作可…

asp提供在线文章翻译的功能(转)

有时候想为我们的网页提供多语言支持&#xff0c;如果一种语言用一张网页来做实在太麻烦了&#xff0c;幸好Google提供了语言工具功能&#xff0c;下面介绍如何利用它来实现网页多种语言之间的转换。 作者&#xff1a;淘特网 出处&#xff1a;http://www.tot.name 注&#xff1…

Java基础学习总结(13)——流IO

2019独角兽企业重金招聘Python工程师标准>>> 一、JAVA流式输入/输出原理 流是用来读写数据的&#xff0c;java有一个类叫File&#xff0c;它封装的是文件的文件名&#xff0c;只是内存里面的一个对象&#xff0c;真正的文件是在硬盘上的一块空间&#xff0c;在这个文…

ASP.NET 2.0 绑定高级技巧

1.简单数据绑定定<!--ASP.NET 1.x data binding expression --><%# DataBinder.Eval(Container.DataItem, "Price") %><!--Equivalent ASP.NET 2.0 data binding expression --><%# Eval("Price") %><!--XML data binding --&g…

JSP中的EL表达式详细介绍

2019独角兽企业重金招聘Python工程师标准>>> 一、JSP EL语言定义 EL 提供了在 JSP 脚本编制元素范围外使用运行时表达式的功能。脚本编制元素是指页面中能够用于在 JSP 文件中嵌入 Java 代码的元素。它们通常用于对象操作以及执行那些影响所生成内容的计算。JSP 2.0…