一个简单的redis的使用场景:
使用redis作为缓存的时候,大部分做法是 先在redis里查询是否有该KEY, 比如查询用户信息时,先在redis里根据用户ID查询,如果没有则到数据库里查询, 如果在数据库里查询到了再放入redis,并设置过期时间,然后返回用户数据。
该场景使用会导致以下3个问题:
1、缓存穿透:指的是redis中不存在该key, 而去查询数据库, 查到后再保存到redis, 查不到则直接返回。
这种情况看上去没毛病,正常业务操作也不会有啥问题。但是一些恶意攻击者可以使用大量不存在的key来攻击你的服务,如数据库 id 是从 1 开始的,结果攻击者发过来的请求 id 全部都是负数。这样的话,当大量不存在的key来请求你的服务时,请求每次都“视缓存于无物”,数据库接受大量的查询,达到一定的限度,这种恶意攻击场景的缓存穿透就会直接把数据库给压垮,造成其他服务不可用。
解决方式 :a、如果数据库根据该KEY未查到数据,不立即返回,先写一个空值到缓存里去,比如 set -999 UNKNOWN,并且过期时间设置小一点。这样的话,下次有相同的一个KEY来恶意访问的时候,在缓存失效之前,都可以直接从缓存中取数据,使得恶意攻击失效。 b、恶意攻击者可能使用不同的不存在的KEY来攻击,这个时候可以用过滤器来过滤掉一部分无效KEY。
2、缓存雪崩:redis中大量的KEY同时过期,或缓存机器意外发生了全盘宕机。缓存挂了&#