缓存击穿:
缓存击穿指的是某一个接口(热点数据)承受了大量的并发请求后,过期失效的瞬间,大量的请求因为没有缓存所以会直接请求到数据库里,给数据库带来巨大的压力。
解决方案1(永不过期):设置热点数据永不过期,但是冷门数据不可能都设永不过期,如果数据库的数据有千万级别,那Redis的压力是极其巨大的。可能有的冷门数据也会在某些时候突然变热门,这时候可以设定一个逻辑,当单位时间内访问量达到一个阈值的时候,再把它设定为热门数据并设置永不过期。
解决方案2(加锁排队):大量并发请求到数据库不是会带来巨大压力吗?那就让它一个个请求就好了,这时候就请求再多也得排队请求。可以使用分布式锁,这样子请求的数量在同一时间就只有一个,但也不一定使用分布式锁,可以使用Java同步锁,这样子同一时间请求的数量最多和挂载的服务器台数的个数,假设有个10台,那也最多10个请求,这种量级的请求数据库也是可以承受的。
缓存雪崩
缓存雪崩指得是当大量热点数据在同一时间过期,大量请求同时落到数据库上,对数据库造成巨大压力导致宕机,从而导致整个服务不可用。
解决方案1(加锁排队):和缓存击穿的原理一样。
解决方案2(设置随机过期时间):不要给数据都设定一样的过期时间,可以设置随机过期时间,这样就不会在某个时候突然有大量数据到期从而导致请求落到数据库上了。
缓存穿透
缓存穿透指的是大量请求在缓存中未命中,在数据库中也没有该数据的时候,每次的请求都会落到数据库中,导致数据库压力过大甚至宕机。(为什么是数据库中也没有该数据呢?因为如果有数据的话,第一次查到了就会缓存到Caffeine或者Redis中,第二次请求就不会落到数据库上了)
解决方案1(校验请求参数):比如请求参数是id,是3位的,然而传过来的却是2位或者4位的,这种id不符的情况就直接不对数据库进行查询,直接过滤掉。
解决方案2(设置空缓存):当缓存中未命中数据时,会查询数据库,要做的就是无论是否查到数据都缓存到Redis中(假如有数据,那下一次同样参数的请求就命中缓存中的数据,假如没数据,下一次同样参数的请求就命中一个空值,避免每次都访问数据库),但是要设置一个过期时间,因为可能现在没有的数据过段时间会添加进数据库里。