缓存穿透

现象

  • 应用服务器压力突然变大

  • redis命中率降低

  • 一直查询数据库

原因

  • redis查询不到数据了

  • 出现了很多非正常的url访问

key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会压到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。

解决方案

  • 对空值缓存
    不管一个查询查询到的数据是否存在都进行缓存,即使为空。设置空的过期时间很短,不超过5分钟。

  • 设置白名单
    使用bitmaps类型定义一个可以访问的名单,名单id作为bitmaps的偏移量,每次访问和bitmap里面的id进行比较,如果访问id不在bitmaps里面,进行拦截,不允许访问。

  • 使用布隆过滤器
    布隆过滤器可用于检索一个数据是否在一个集合中,他的优点是时间和空间都超过一搬的算法。缺点是有一定的概率误识别和删除困难。
    将所有可能存在的数据hash到一个足够大的bitmaps中,一个一定不存在的数据会被bitmaps拦截掉。从而避免对底层存储系统的查询压力。

缓存击穿

现象

  • 数据库中访问压力瞬间增加

  • redis没有出现大量key过期

  • redis正常 运行

原因

  • redis中某个key过期了,大量使用这个key

解决方案

  • 预先设置热门数据:在redis高峰访问之前,吧一些热门数据提前存入到redis里面,加大这些热门数据key的时长

  • 实时调整:现场监控哪些数据热门,实时调整key的 过期时长

  • 使用锁

    • 在缓存失效 的时候(判断拿出来 的值为空),不是立即去load db

    • 先使用缓存工具的某些带成功操作返回值的操作(比如redis的setnx)去set一个mutex key。

    • 当操作返回成功时,再进行load db的操作,并回设缓存,最后删除mutex key.

    • 当操作返回失败,说明有其他线程在load db,当前线程睡眠一段时间再重试整个get缓存的方法。

缓存雪崩

现象

  • 数据库压力变大,服务器崩溃

原因

  • 在极少的时间内,出现了大量key集中过期的情况

压垮骆驼的最后一根稻草。
key对应的数据存在,但在redis中大量过期,若此时有大量请求进来,这些请求发现缓存过期后会从后端db加载数据,并会设到缓存。这时候如果大并发的请求可能会瞬间把后端db压垮。

解决方案

  • 设置多级缓存:nginx缓存,redis缓存,其他缓存

  • 使用锁或者队列,用加锁的方式来保证不会有大量线程对数据库进行一次性读写,从而避免缓存失效的时候大量请求落在db上。不适用于高并发情况。

  • 记录缓存数据是否过期,(设置提前量),如果过期,会触发通知另外的线程在后台去更新实际key的缓存。

  • 将缓存失效时间分散开,可以在原有的时间上加上1-5分钟的随机值。这样每一个缓存过期时间的重复率就会降低。就很难引发集体失效。

区别

缓存雪崩和缓存击穿的区别

定义和原因:

缓存击穿:指在使用缓存系统时,当某个特定的热点数据失效,并且在该数据失效的时候有大量的请求同时涌入,超过了缓存的承载能力,导致请求直接绕过缓存查询后端数据源,给后端系统带来过大的压力。
缓存雪崩:指在使用缓存系统时,缓存中的大量数据同时失效(例如缓存中的数据过期或缓存系统崩溃),导致大量请求直接访问后端存储系统,给后端系统带来巨大的负载压力。

原因不同:

缓存击穿的原因是针对某一个特定的热点数据失效引起的,当该数据失效时,大量请求同时访问,导致缓存无法提供服务。
缓存雪崩的原因是缓存中的大量数据失效,可以是同时过期或缓存系统故障,导致大量请求直接访问后端存储系统。

影响范围不同:

缓存击穿通常只涉及到某个特定的热点数据,其他数据的缓存不受影响。
缓存雪崩会影响到缓存中大量数据,导致整个系统的性能下降,甚至可能导致系统瘫痪。

解决方法不同:

缓存击穿的常见解决方法包括设置热点数据的永不过期策略、使用互斥锁等。
缓存雪崩的常见解决方法包括错开缓存数据的过期时间、引入多级缓存、实施熔断机制等。

分类: java

浙公网安备33011302000604

辽ICP备20003309号