问题
大量的请求到数据库去查询。可能会导致数据库由于压力过大而宕掉。
缓存穿透:
请求查询一条数据库中不存在的数据,即缓存和数据库都查询不到这条数据,因此请求每次都会打到数据库上面去。
解决办法
缓存空值: 缓存中存储这些空数据的key。(也要设置过期时间)
BloomFilter布隆过滤器(位数组+hash函数)
针对这种key异常多、请求重复率比较低的数据,没有必要进行缓存,使用BloomFilter直接过滤掉。
对于空数据的key有限的,重复率比较高的,采用缓存空值方式。
布隆过滤器(Bloom Filter)的原理和实现
BloomFilter 类似于一个hbase set 用来判断某个元素(key)是否存在于某个集合中。
查询的时候先去 BloomFilter 去查询 key 是否存在,如果不存在就直接返回,存在再走查缓存 -> 查 DB。
缓存击穿:
高并发的系统中,大量的请求同时查询一个 key 时,而恰好这个key失效了,导致大量的请求都打到数据库上。
解决办法
互斥锁
多个线程同时去查询数据库的某条数据,在第一个查询数据的请求上使用一个 互斥锁来锁住它。
其他的线程被阻塞,等第一个线程查询到了数据,做缓存后。后面的线程进来发现已经有缓存了,就直接走缓存。
缓存雪崩:
大规模的缓存失效(如缓存服务宕机)
解决办法
事前:使用集群缓存,保证缓存服务的高可用
如使用 Redis,可以使用 主从+哨兵 ,Redis Cluster 来避免 Redis 全盘崩溃的情况。
事中:ehcache本地缓存 + Hystrix限流&降级
在 Redis Cluster 完全不可用的时候,ehcache 本地缓存还能够支撑一阵。
事后:开启Redis持久化机制,尽快恢复缓存集群
热点数据失效:
大量热点数据的key设置的超时时间过期
解决办法
设置缓存过期时间时,在基础时间上加减随机值。
互斥锁