一、缓存功能
当系统处于高并发时,为了防止数据库压力过大,引入缓存处理功能,流程如下:
当引入缓存功能后,会引发出问题:(1)缓存穿透,(2)缓存击穿,(3)缓存雪崩。
二、缓存穿透
解释:缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击 者,攻击会导致数据库压力过大。
注意:不能避免低频的缓存穿透,可以避免高频的缓存穿透。
解决办法:
- 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
- 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null存入缓存中,缺点:当用户不断地以大量不同的key(缓存层和数据库)去访问时,缓存层就会存储大量的(key-null),所以会占用过多的内存,此时需要设置缓存有效期,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击。
- 在server端存储一个布隆过滤器,将mysql包含的key放如布隆过滤器中,布隆过滤器能过滤一定不存在的数据。
四、缓存雪崩
解释:缓存层在同一时刻,大量缓存的数据同时失效,导致大量的请求跑到数据库。
导致原因:
(1)redis中缓存的数据有效期是一致的,然后失效也就是同一时刻。
解决办法:给每一条数据加上一个随机有效期,不要突然同时失效。
(2)redis数据库挂掉了
解决办法:分布式缓存。
五、缓存击穿
解释:当缓存层(redis)只缓存了1条数据时,当用户大量的请求过来时,刚好这条数据失效。
解决办法:分布式锁(基于mysql或者基于Zookeeper)