缓存雪崩 Cache Avalanche 缓存穿透 Cache Penetration 缓存击穿 Hotspot Invalid

一.无处不在的缓存
缓存在计算机系统是无处不在,在CPU层面有L1-L3的Cache,在Linux中有TLB加速虚拟地址和物理地址的转换,在应用层有Redis等内存数据库缓存、在浏览器有本地缓存、手机有本地文件缓存等等。
可见,缓存在计算机系统中有非常重要的地位,主要作用就是提高响应速度、减少磁盘读取等,本文主要讨论在高并发系统中的缓存系统。一句话概括缓存系统在高并发系统中的地位的话,就是:

如果高并发系统是烤羊肉串,那么缓存系统就是那一撮孜然......

二.高并发系统中的缓存

  • 缓存系统的作用

缓存系统在高并发系统的作用巨大,没有缓存系统很难支撑C50K(或许这个值已经非常乐观了)以上的场景。
基于机械磁盘或SSD的数据库系统,读写的速度远慢于内存,因此单纯磁盘介质的数据库无法支撑高并发,你可以认为缓存就是为了保护磁盘数据库、是磁盘数据库的屏障。

  • 缓存系统和数据库系统的访问

以读多写少的场景为例(实际场景也是读多写少),看看请求是如何得到响应的,简单流程:请求到达之后,业务线程首先访问缓存,如果缓存命中则返回,如果未命中则继续请求磁盘数据库系统,并将结果回写到缓存系统且增加老化时间,这样在超时时间内再有相同请求到达时则可以命中缓存。以上是高并发系统中缓存和磁盘数据库系统、客户端请求之间的交互过程,后续的问题分析,也是基于此过程展开的。

三.缓存系统的三大问题
网络上对于缓存三大问题的文章很多,提到的三个问题主要是:

  1. 缓存雪崩 Cache Avalanche
  2. 缓存穿透 Cache Penetration
  3. 缓存击穿 Hotspot Invalid

对于上面的三个名词我一直分不清楚,脑海中并没有清晰的区别,于是想到去谷歌看看歪果仁是怎么说的,然而英文表述就是上面的英文,基本上和汉语翻译是一样的,所以只能强记了。

A.缓存雪崩问题

所谓雪崩就是原来有所支撑的冰雪,某一瞬间失去依托,瞬间涌下来。这个场景让我想起了2011年上映的柯南剧场版《沉默的十五分钟》,柯南在北泽村水库为了拯救村庄制造的雪崩:

注:图为柯南被雪崩所埋,黄金抢救期时毛利兰在寻找他的镜头

可见雪崩确实很可怕,回到高并发系统,如果缓存系统故障,大量的请求无法从缓存完成数据请求,因此就全量汹涌冲向磁盘数据库系统,导致数据库被打死,整个系统彻底崩溃。

缓存雪崩解决方案

从原因来看主要是缓存系统不够高可用,因此提高缓存系统的稳定性和可用性十分必要,对于使用Redis作为缓存的系统而言需要使用Sentinel哨兵机制、集群化、持久化等来提高缓存系统的HA。

另一方面除了保证缓存系统的HA之外,服务本身也需要支持降级,可以使用奈飞的Hystrix来实现服务的熔断、降级、限流来降低出现雪崩时的故障程度。说白了就是别让服务彻底死掉就行,就像大雪封高速肯定彻底不能通行了,堵车就是慢一些至少可以走,如果还不清楚,回想一下每年你回乡的车票是怎么从12306抢回来的。

B.缓存穿透问题

穿透形象一点就是:请求过来了 转了一圈 一无所获 就像穿过透明地带一样。

在高并发系统中缓存穿透,其实是这样的如果一个req需要请求的key在缓存中没有,这时业务线程就会访问磁盘数据库系统,然而磁盘数据库也没有这个key,无奈业务线程只能返回null,白白处理一圈。
小概率事件在高并发系统几乎要成为必然,也就是如果某时段有大量恶意的不存在的key的爆破请求,那么服务将一直处理这些根本不存在的请求,导致正常请求无法被处理,从而出现问题。
举个栗子:

拉面馆的服务员和厨师不允许拒绝已经进来的消费者,但是拉面馆的经营范围有限,此时恶意消费者点了一只5斤的澳洲龙虾,经过服务员和厨师都无法响应这个需求,因此被最终被拒绝,此时轮流来了1000个这样的恶意消费者,拉面馆基本要歇菜了。

缓存穿透解决方案

高并发系统也是如此,有效甄别是否存在这个key再决定是否读取很重要,常见的做法有:

a.把不存在的key写一下null,这样再来就相当于命中了,其实这种方法局限性很大,今天是5斤龙虾,明天改成6斤的螃蟹,缓存系统和数据库中存储大量无用key本身是无意义的,所以一般不建议。
 b.另外一种思路,转换为查找问题,类似于在海量数据中查找某个key是否存在,考虑空间复杂度和时间复杂度,一般选用布隆过滤器来实现。

缓布隆过滤器简介

布隆过滤器是个好东西,在1970年由布隆提出的,它实际上是一个很长的二进制向量和一系列随机映射函数。

布隆可以实现的系统包括:垃圾邮件识别、搜索蜘蛛爬虫url去重等,主要借助K个哈希函数和一个超大的bit数组来降低哈希冲突本身带来的误判,从而提高识别准确性。
布隆过滤器也存在一定的误判,假如判断存在可能不一定存在,但是假如判断不存在就一定不存在,因此刚好用在解决缓存穿透的key查找场景,事实上很多系统都是基于布隆过滤器来解决缓存穿透问题的。

C.缓存击穿问题

缓存击穿是这样一种情况:由于缓存系统中的热点数据都有过期时间,如果没有过期时间就造成了主存和缓存的数据不一致,因此过期时间一般都不会太长,设想某时刻一批热点数据同时在缓存系统中过期失效,那么这部分数据就都将请求磁盘数据库系统。
从描述上来看有点像微小规模的雪崩,但是对数据库的压力就很小了,只不过会影响并发性能,然而在多线程场景中缓存击穿却是经常发生的,相反缓存穿透和雪崩频率不如缓存击穿,因此研究击穿的现实意义更大一些

缓存击穿解决方案

可以采用的方案大概有几种:

a. 在设置热点数据过期时间时尽量分散,比如设置100ms的基础值,在此基础上正负浮动10ms,从而降低相同时刻出现CacheMiss的key的数量。
b. 另外一种做法是多线程加锁,其中第一个线程发现CacheMiss之后进行加锁,再从数据库获取内容之后写到缓存中,其他线程获取锁失败则阻塞数ms之后再进行缓存读取,这样可以降低访问数据数据库的线程数,需要注意在单机和集群需要使用不同的锁,集群环境使用分布式锁来实现,但是由于锁的存在也会影响并发效率。
c.还有一种办法是使用类似于Redis的SETNX命令,这种貌似存在问题,存在一个gap间隙请求处于无法从缓存获取数据也无法从主存获取数据的未决状态。
d. 最后一种方法是在业务层对使用的热点数据查看是否即将过期,如果即将过期则去数据库获取最新数据进行更新并延长该热点key在缓存系统中的时间,从而避免后面的过期CacheMiss,相当于把事情提前解决了。

缓存击穿的解决方法都有一定的权衡,实际中根据自己的需求来解决,不过缓存击穿的影响一般来说并不会太大,或许在你的服务跑了很久之后你才意识到会有缓存击穿问题。

原文地址:https://www.cnblogs.com/Leo_wl/p/12294093.html

时间: 2024-07-29 22:09:21

缓存雪崩 Cache Avalanche 缓存穿透 Cache Penetration 缓存击穿 Hotspot Invalid的相关文章

数据库 | Redis 缓存雪崩解决方案

Redis 雪崩 缓存层承载着大量的请求,有效保护了存储层.但是如果由于缓存大量失效或者缓存整体不能提供服务,导致大量的请求到达存储层,会使存储层负载增加,这就是缓存雪崩的场景. 解决缓存雪崩,可以从以下几个方面入手. 1.保持缓存层的高可用性 使用Redis 哨兵模式或者Redis 集群部署方式,即便个别Redis 节点下线,整个缓存层依然可以使用.除此之外,还可以在多个机房部署 Redis,这样即便是机房死机,依然可以实现缓存层的高可用. 2.限流降级组件 无论是缓存层还是存储层都会有出错的

缓存穿透,缓存击穿,缓存雪崩解决方案分析

本文转自:http://blog.csdn.net/zeb_perfect/article/details/54135506 前言 设计一个缓存系统,不得不要考虑的问题就是:缓存穿透.缓存击穿与失效时的雪崩效应. 缓存穿透 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义.在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞

缓存穿透、缓存雪崩

1.缓存穿透 访问一个不存在的key,缓存不起作用,请求会穿透到DB,流量大时DB会挂掉. 解决: 1)采用布隆过滤器,使用一个足够大的bitmap,用于存储可能访问的key,不存在的key直接被过滤: 2)拦截器,id<=0的直接拦截. 3)从cache和db都取不到,可以将key-value写为key-null,设置较短过期时间,如30秒(设置太长会导致正常情况也没法使用).这样可以防止攻击用户反复用同一个id暴力攻击 2.缓存雪崩      大量的key设置了相同的过期时间,导致在缓存在同

缓存穿透缓存雪崩,缓存击穿,django的6种缓存数据

缓存穿透,是指查询一个数据库一定不存在的数据.正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存.如果数据库查询对象为空,则不放进缓存. 想象一下这个情况,如果传入的参数为-1,会是怎么样?这个-1,就是一定不存在的对象.就会每次都去查询数据库,而每次查询都是空,每次又都不会进行缓存.假如有恶意攻击,就可以利用这个漏洞,对数据库造成压力,甚至压垮数据库.即便是采用UUID,也是很容易找到一个不存在的KEY,进行攻击

缓存雪崩与缓存穿透

缓存雪崩与缓存穿透 今天来分享一下Redis几道常见的面试题: 如何解决缓存雪崩? 如何解决缓存穿透? 如何保证缓存与数据库双写时一致的问题? 一.缓存雪崩 1.1 什么是缓存雪崩? 首先我们先来回答一下我们为什么要用缓存(Redis): 1.提高性能能:缓存查询是纯内存访问,而硬盘是磁盘访问,因此缓存查询速度比数据库查询速度快 2.提高并发能力:缓存分组了部分请求,支持更高的并发 现在有个问题,如果我们的缓存挂掉了,这意味着我们的全部请求都跑去数据库了. 我们都知道Redis不可能把所有的数据

缓存穿透,缓存击穿,缓存雪崩的原理及解决方案

前言 设计一个缓存系统,不得不要考虑的问题就是:缓存穿透.缓存击穿与失效时的雪崩效应 缓存穿透 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义.在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞.举例:如发起为id为"-1"的数据或id为特别大不存在的数据.这时的用户很可能是攻击者,攻击会导致数据库压力过大.

如何设计缓存系统:缓存穿透,缓存击穿,缓存雪崩解决方案分析

前言 设计一个缓存系统,不得不要考虑的问题就是:缓存穿透.缓存击穿与失效时的雪崩效应. 缓存穿透 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义. 在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞. 解决方案 有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bi

缓存穿透与缓存雪崩

缓存穿透 什么是缓存穿透? 一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB).如果key对应的value是一定不存在的,并且对该key并发请求量很大,就会对后端系统造成很大的压力.这就叫做缓存穿透. 如何避免? 1:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存. 2:对一定不存在的key进行过滤.可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤.[感觉

关于缓存中Cookie,Session,Cache的使用

文章来源:http://canann.iteye.com/blog/1941173 以前实现数据的缓存有很多种方法,有客户端的Cookie,有服务器端的Session和Application. 其中Cookie是保存在客户端的一组数据,主要用来保存用户名等个人信息. Session则保存对话信息.Application则是保存在整个应用程序范围内的信息,相当于全局变量. Session Session用来保存每一个用户的专有信息 Session的生存期是用户持续请求时间加上一段时间(一般是20分