Redis 缓存过期、淘汰、穿透、击穿、雪崩

2021-08-02  本文已影响0人  SheHuan

在实际的业务场景中,我们经常会用 MySQL 存储数据,随着业务的发展,数据量也会越来越大,这样数据库操作的 I/O 效率会越来越差、耗时,影响性能以及用户体验。而且大多数的用户请求都是查询操作,还可能出现大量重复的查询请求,比如 618 查询热门商品等。

本着缓解 MySQL 数据库压力,提高用户用户体验的初衷,我们一般会考虑使用 Redis 来配合 MySQL,Redis 将数据放在内存中,查询效率极高。将一些查询频率高的数据缓存到 Redis,这样用户的查询请求过来后,先去 Redis 中看有没有数据,没有的话再去 MySQL 查询。

虽然加入 Redis 可以在一定程度上解决问题,但是也产生了一些新的问题,需要注意!

一、缓存过期策略

我们知道 Redis 会将数据放在内存中,但内存资源毕竟是有限的,不可能无限制的存储,要不然内存迟早会爆掉。

这就要用到了 Redis 的缓存过期策略了,给 key 设置过期时间,设置了过期时间的 key 会被存储到一个字典中,根据不同的策略,在达到过期时间后最终被删除掉。

但是有些 key 可能运气比较好,虽然已经过期,但是逃过了上边两种删除策略,继续占用内存。可能还有一些 key 设置的过期时间超长,还没过期内存就快爆满了。所以缓存过期策略还是有一定的局限性,需要缓存淘汰策略来弥补它的局限性。

二、缓存淘汰策略

当 Redis 内存不足时,可以通过配置一些缓存淘汰策略,来应对内存不足的问题。在配置文件中使用maxmemory-policy来设置不同的策略。

先来看一下都有哪些策略:

一般使用volatile-lruallkeys-lru就可以满足我们的需求,会删除最近最少使用的数据,也相对合理一些。当然具体如何选择淘汰策略还需要根据你的实际场景分析。

三、缓存穿透

前边我们说过,加入了 Redis 缓存后,客户端查询数据时,先去 Redis 中看有没有,没有的话再去 MySQL 查询。但是,如果客户端请求要查询的数据,在 Redis 缓存中没有,在 MySQL 中也没有,这样 Redis 缓存将形同虚设,MySQL 也要做无用的查询操作,这就是缓存穿透。

如果有大量的请求都是查询一些根本不存在的数据,会给数据库造成一定的压力,如果是可以攻击,可能把数据库都搞挂了,所以有必要在处理查询请求前,先判断要查询的数据是否存在,不存在就直接返回结果,不要让数据库做无用功。

这个问题可以使用布隆过滤器解决,布隆过滤器非常适合在大量的数据中判断指定数据是否存在,如果结果是不存在那就肯定不存在,但如果结果是存在就不能保证一定存在了。

所以,可以把查询相关的关键数据预先放到布隆过滤器中,这样请求过来了先判断布隆过滤器中是否有要查询的数据,如果布隆过滤器中不存在就不要做后续的查询操作了,可以过滤掉大量无效的查询。

三、缓存击穿、雪崩

如果缓存中某个数据到了过期时间,被删除掉了,不巧随后又有大量的请求都是针对该数据的查询,此时缓存就起不到作用了,所有的请求都需要 MySQL 处理,造成 MySQL 瞬间压力山大,这种现象就是缓存击穿。

上边只是某一个数据过期了,如果缓存中大批量数据过期被删了,更不巧的是随后又过来了大量针对这些过期数据的查询,MySQL 可能扛不住住压力,就挂掉了, 这就是缓存雪崩,像是升级版的缓存击穿。

下边是解决缓存击穿、雪崩的一些方案:

上一篇 下一篇

猜你喜欢

热点阅读