面试题答案
一键面试缓存雪崩
- 产生原因:大量缓存数据在同一时间过期(比如设置了相同的过期时间),或者缓存服务器发生故障宕机,此时大量请求直接落到数据库,导致数据库压力瞬间增大,甚至可能压垮数据库。
- 预防和解决方法:
- 设置随机过期时间:为缓存数据设置不同的过期时间,避免大量数据同时过期。例如原本过期时间是1小时,可以在50 - 70分钟之间随机取值。
- 多级缓存:采用多级缓存架构,如本地缓存(如Guava Cache)和分布式缓存(如Redis)结合。当分布式缓存失效时,先从本地缓存获取数据,减轻数据库压力。
- 缓存预热:在系统启动前,提前将部分热点数据加载到缓存中,避免系统刚启动时大量请求查询不到缓存而直接访问数据库。
- 高可用:搭建缓存集群,采用主从复制、哨兵模式或集群模式,保证缓存服务的高可用性,减少因缓存服务器故障导致的雪崩。
缓存穿透
- 产生原因:查询一个不存在的数据,每次都查询不到缓存,请求直接穿透到数据库。如果大量这种请求同时出现,会对数据库造成巨大压力。常见于恶意攻击,如黑客故意大量请求不存在的键值。
- 预防和解决方法:
- 布隆过滤器:在缓存之前使用布隆过滤器,将所有可能存在的数据哈希到一个足够大的位数组中。当查询时,先经过布隆过滤器判断,如果过滤器判断数据不存在,则直接返回,不再查询数据库,避免无效查询穿透到数据库。
- 空值缓存:当查询数据库也没有找到数据时,将该查询结果(空值)也缓存起来,并设置较短的过期时间,这样下次相同查询就直接从缓存返回,不会再穿透到数据库。
缓存击穿
- 产生原因:缓存中一个热点数据过期的瞬间,大量并发请求同时访问该数据,由于缓存过期,这些请求都会直接访问数据库,导致数据库压力瞬间增大。
- 预防和解决方法:
- 互斥锁:在查询缓存失效时,先获取一个分布式锁(如Redis的SETNX命令实现),只有获取到锁的请求才能查询数据库并更新缓存,其他请求等待锁释放后从缓存获取数据。这种方式可以有效避免大量请求同时查询数据库。
- 永不过期:对于热点数据设置永不过期,同时使用后台线程定时更新缓存数据,或者在数据发生变化时主动更新缓存,这样可以避免热点数据过期瞬间的高并发问题。