使用 redis 需要注意的安全问题| 青训营笔记

214 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第 5 篇笔记。

Redis作为目前使用最广泛的高性能的分布式内存数据库,大家并不陌生。但是使用缓存并没有这么简单,还要考虑缓存雪崩,缓存击穿,缓存穿透的问题。本片介绍在 redis 使用中对这些问题的处理方案。

缓存穿透

当查询 Redis 中没有的数据时,该查询会下沉到数据库层,同时数据库层也没有该数据,当这种情况大量出现或被恶意攻击时,接口的访问全部透过 Redis 访问数据库,而数据库中也没有这些数据,我们称这种现象为"缓存穿透"。缓存穿透会穿透 Redis 的保护,提升底层数据库的负载压力,同时这类穿透查询没有数据返回也造成了网络和计算资源的浪费。
(需要注意的是针对缓存穿透的攻击往往不只针对某一特定数据,而是随机多个不存在的数据进行攻击)

image.png

缓存穿透解决方案

方案一

解决方案:把空对象缓存起来。当第一次从数据库中查询出来的结果为空时,我们就将这个空对象加载到缓存,并设置合理的过期时间,这样,就能够在一定程度上保障后端数据库的安全。

方案二

使用布隆过滤器,布隆过滤器可以针对大数据量的、有规律的键值进行处理。一条记录是不是存在,本质上是一个Bool值,只需要使用 1bit 就可以存储。我们可以使用布隆过滤器将这种表示是、否等操作,压缩到一个数据结构中。

  • 如果Redis内不存在该数据,则通过布隆过滤器判断数据是否在底层数据库内;
  • 如果布隆过滤器告诉我们该key在底层库内不存在,则直接返回null给客户端即可,避免了查询底层数据库的动作;
  • 如果布隆过滤器告诉我们该key极有可能在底层数据库内存在,那么将查询下推到底层数据库即可;

缓存击穿

某一时刻有大量的 redis 缓存过期,导致该时刻大量 redis 查询为空,从而转向数据库查询给服务器带来负担。

image.png

解决方案

使用分布式锁,保证对于每个Key同时只有一个线程去查询后端的服务,某个线程在查询后端服务的同时,其他线程没有获得分布式锁的权限,需要进行等待。

缓存雪崩

缓存雪崩是缓存击穿的"大面积"版,缓存击穿是数据库缓存到Redis内的热点数据失效导致大量并发查询穿过redis直接击打到底层数据库,而缓存雪崩是指Redis中大量的key几乎同时过期,然后大量并发查询穿过redis击打到底层数据库上,此时数据库层的负载压力会骤增,我们称这种现象为"缓存雪崩"。

image.png

解决方案

在可接受的时间范围内随机设置key的过期时间,分散key的过期时间,以防止大量的key在同一时刻过期。