-
缓存穿透:当查询一个不存在的数据时,存储层并不会将查询不到的数据进行缓存,这就导致了每次查询不存在的数据时,都会访问数据库,访问次数过大就会导致数据库挂掉,这种情况很可能就是遭到了恶意攻击。
-
解决方案一:缓存空数据。查询返回结果为空,并且把空数据进行缓存,实现简单,但是消耗内存,可能会发生数据不一致的问题
-
解决方案二:布隆过滤器。
布隆过滤器主要作用是判断一个元素是否在一个集合中,我们当时使用的是redisson实现的布隆过滤器。布隆过滤器的底层原理是初始化一个大的数组,初始元素全部为0。标记的过程是当一个Key来到时,会经过三个Hash函数得到的数值再模数组的长度得到三个下标,将这三个下标对应的位置的元素从0改为1,这三个位置就标记了这个Key存在,查询的过程是一样的。到那时布隆过滤器会有误判,当数组开的越大时误判率就会越低但是消耗内存也就越大。一般来说误判率小于百分之五是可以接受的,不至于高并发下压倒数据库。
-
-
缓存击穿:当一个Key设置了过期时间的时候,当这个Key过期时,恰好有对这个Key的大量访问请求,这些并发的请求可能会一瞬间击垮数据库。
-
解决方案一:互斥锁
强一致性,但是性能差
简单来说就是查询缓存中不存在数据的时候,需要一个一个排队去访问数据库,防止了在同一时间大量的强求访问数据库,从而避免了大量查询击跨数据库。
-
解决方案二:逻辑过期
热点Key在redis中不设置过期时间,而是增加一个逻辑字段
高可用,性能优
-
-
雪崩
在同一时间段大量的缓存key同时失效或redis服务器宕机,导致大量请求到达数据库,带来巨大压力。
- 解决方法一:给不同key的TTL添加随机值。
- 解决方法二:如果redis服务器宕机,利用redis集群提高服务的可用性,例如:哨兵模式、集群模式。
- 解决方法三:给缓存业务添加降级限流策略,例如:nginx或Spring cloud gateway,可作为系统的保底策略,适用于穿透、击穿、雪崩。
- 解决方法三:给业务添加多级缓存,例如:Guava或Caffeine