文档章节

缓存相关——缓存穿透、缓存并发、缓存失效、缓存预热、缓存雪崩、缓存算法

空云万里晴
 空云万里晴
发布于 2016/06/16 11:02
字数 1341
阅读 1830
收藏 17

一、缓存穿透

我们在项目中使用缓存通常都是先检查缓存中是否存在,如果存在直接返回缓存内容,如果不存在就直接查询数据库然后再缓存查询结果返回。这个时候如果我们查询的某一个数据在缓存中一直不存在,就会造成每一次请求都查询DB,这样缓存就失去了意义,在流量大时,可能DB就挂掉了。

那这种问题有什么好办法解决呢?

要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。 
有一个比较巧妙的作法是,可以将这个不存在的key预先设定一个值。 
比如,”key” , “&&”。 
在返回这个&&值的时候,我们的应用就可以认为这是不存在的key,那我们的应用就可以决定是否继续等待继续访问,还是放弃掉这次操作。如果继续等待访问,过一个时间轮询点后,再次请求这个key,如果取到的值不再是&&,则可以认为这时候key有值了,从而避免了透传到数据库,从而把大量的类似请求挡在了缓存之中。

二、缓存并发

有时候如果网站并发访问高,一个缓存如果失效,可能出现多个进程同时查询DB,同时设置缓存的情况,如果并发确实很大,这也可能造成DB压力过大,还有缓存频繁更新的问题。

我现在的想法是对缓存查询加锁,如果KEY不存在,就加锁,然后查DB入缓存,然后解锁;其他进程如果发现有锁就等待,然后等解锁后返回数据或者进入DB查询。

这种情况和刚才说的预先设定值问题有些类似,只不过利用锁的方式,会造成部分请求等待。

三、缓存失效

引起这个问题的主要原因还是高并发的时候,平时我们设定一个缓存的过期时间时,可能有一些会设置1分钟啊,5分钟这些,并发很高时可能会出在某一个时间同时生成了很多的缓存,并且过期时间都一样,这个时候就可能引发一当过期时间到后,这些缓存同时失效,请求全部转发到DB,DB可能会压力过重。

那如何解决这些问题呢? 
其中的一个简单方案就时讲缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

四、缓存雪崩

缓存雪崩可能是因为数据未加载到缓存中,或者缓存同一时间大面积的失效,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机。

解决思路:

1,采用加锁计数,或者使用合理的队列数量来避免缓存失效时对数据库造成太大的压力。这种办法虽然能缓解数据库的压力,但是同时又降低了系统的吞吐量。

2,分析用户行为,尽量让失效时间点均匀分布。避免缓存雪崩的出现。

3,如果是因为某台缓存服务器宕机,可以考虑做主备,比如:redis主备,但是双缓存涉及到更新事务的问题,update可能读到脏数据,需要好好解决。

五、缓存预热

单机web系统情况下比较简单。

解决思路:

1,直接写个缓存刷新页面,上线时手工操作下。

2,数据量不大,可以在WEB系统启动的时候加载。

3,搞个定时器定时刷新缓存,或者由用户触发都行。

分布式缓存系统,如Memcached,Redis,比如缓存系统比较大,由十几台甚至几十台机器组成,这样预热会复杂一些。

解决思路:

1,写个程序去跑。

2,单个缓存预热框架。

缓存预热的目标就是在系统上线前,将数据加载到缓存中。

六、缓存算法

FIFO算法:First in First out,先进先出。原则:一个数据最先进入缓存中,则应该最早淘汰掉。也就是说,当缓存满的时候,应当把最先进入缓存的数据给淘汰掉。
LFU算法:Least Frequently Used,最不经常使用算法。
LRU算法:Least Recently Used,近期最少使用算法。请查看:Memcached之你真正理解LRU吗(4)

LRU和LFU的区别。LFU算法是根据在一段时间里数据项被使用的次数选择出最少使用的数据项,即根据使用次数的差异来决定。而LRU是根据使用时间的差异来决定的。

© 著作权归作者所有

共有 人打赏支持
空云万里晴

空云万里晴

粉丝 64
博文 52
码字总数 33031
作品 0
广州
高级程序员
缓存雪崩,缓存穿透,缓存预热,缓存热备都是什么鬼?

QQ用得起来越少了,现在就加入300+技术微信群,下方公众号回复"微信群"即可加入。 公众号:java技术栈,每日更新 缓存雪崩,缓存穿透,缓存预热,缓存热备是在做缓存设计或者缓存应用时经常遇...

架构之路
2017/11/30
0
0
Memcached全面剖析

整个网站应用中,缓存几乎无处不在,既存在于浏览器、也存在于应用服务器和数据库服务器;既可以对数据缓存(分布式缓存),也可以对文件缓存(分布式存储系统),还可以对页面片段缓存(ESI...

亚特兰缇斯
2016/04/03
42
0
面对海量请求,缓存设计还应该考虑哪些问题?

  【IT168 技术】从第一个缓存框架 Memcached 诞生以来,缓存就广泛地存在于互联网应用中。如果你的应用流量很小,那么使用缓存可能并不需要做多余的考虑。但如果你的应用流量达到了成百上...

博客园
05/23
0
0
面对海量请求,缓存设计还应该考虑哪些问题?

从第一个缓存框架 Memcached 诞生以来,缓存就广泛地存在于互联网应用中。如果你的应用流量很小,那么使用缓存可能并不需要做多余的考虑。但如果你的应用流量达到了成百上千万,那么你就不得...

陈树义
05/15
0
0
并发经验八年架构师:缓存在高并发场景下该如何问题

缓存一致性问题 当数据时效性要求很高时,需要保证缓存中的数据与数据库中的保持一致,而且需要保证缓存节点和副本中的数据也保持一致,不能出现差异现象。这就比较依赖缓存的过期和更新策略...

Java架构分享
04/22
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

[MicroPython]STM32F407开发板驱动OLED液晶屏

1.实验目的 1.学习在PC机系统中扩展简单I/O 接口的方法。 2.进一步学习编制数据输出程序的设计方法。 3.学习 F407 Micropython开发板控制OLED显示字符。 2.所需元器件 F407 Micropython开发板...

bodasisiter
27分钟前
0
0
php require和include 相对路径一个有趣的坑

以前总是被教育,不要使用相对路径,这样性能比较差,但是相对路径的问题不仅仅是性能哦,看下面这里例子 这是项目结构 .├── main.php├── t│ ├── t1.php│ └── t2.php└─...

anoty
28分钟前
15
0
x64技术之SSDT_Hook

测试环境: 虚拟机: Windows 7 64bit 过PG工具 驱动加载工具 PCHunter64 系统自带的计算器和任务管理器等 实现思路: 实际思路与win32的思路一样.都是替换SSDT表里边的函数地址.不过微软被搞怕...

simpower
29分钟前
0
0
TreeMap源码分析,看了都说好

一、简介 TreeMap最早出现在JDK 1.2中,是 Java 集合框架中比较重要一个的实现。TreeMap 底层基于红黑树实现,可保证在log(n)时间复杂度内完成 containsKey、get、put 和 remove 操作,效率很...

Java小铺
39分钟前
0
0
协变、逆变

概念 假设 A、B表示类型 ≤ 表示继承关系 f<⋅>表示类型转换 若A ≤ B,则 A是B的子类,B是A的超类 协变、逆变 什么是型变?型变(type variance)允许对类型进行子类型转换。 为了下面讲解先...

obaniu
45分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部