面试题答案
一键面试缓存击穿问题
- 产生原因:
- 大量并发请求同时查询一个在Redis中过期但在MySQL中存在的数据。此时,缓存中没有该数据,所有请求都直接穿透到数据库,导致数据库瞬间承受巨大压力,可能引发数据库性能问题甚至崩溃。
- 解决方案及优缺点:
- 方案一:使用互斥锁(Mutex)
- 实现方式:在缓存失效时,先获取一个互斥锁(如Redis的SETNX命令),只有获取到锁的请求才能去数据库查询数据并回设到缓存,其他请求等待。获取锁的请求完成后释放锁。
- 优点:简单有效,能防止大量请求同时穿透到数据库。
- 缺点:增加了锁的开销,可能会导致其他请求等待时间过长,降低系统并发性能。如果获取锁的请求在数据库查询时出现异常,未能及时释放锁,可能会造成死锁,影响后续请求。
- 方案二:永不过期策略
- 实现方式:在Redis中设置数据时,不设置过期时间,同时在应用层启动一个异步线程,定期对数据进行更新。或者使用逻辑过期,即数据中存储一个过期时间字段,每次读取数据时判断是否逻辑过期,若过期则异步更新数据。
- 优点:避免了缓存过期瞬间大量请求穿透到数据库的问题,系统并发性能较好。
- 缺点:如果异步更新不及时,可能会导致数据长时间不一致。对于逻辑过期,每次读取都要增加判断逻辑,增加了应用层的复杂度。
- 方案一:使用互斥锁(Mutex)
缓存雪崩问题
- 产生原因:
- 大量的缓存数据在同一时间过期,或者Redis服务发生故障,此时大量请求无法从缓存获取数据,全部转向数据库,使数据库压力剧增,可能导致数据库崩溃,进而影响整个系统的可用性。
- 解决方案及优缺点:
- 方案一:设置随机过期时间
- 实现方式:在设置缓存过期时间时,不采用固定的过期时间,而是设置一个随机的过期时间范围。例如,原本过期时间为1小时,现在设置为50分钟到70分钟之间的随机值。这样可以避免大量缓存同时过期。
- 优点:简单易实现,能有效分散缓存过期时间,降低缓存雪崩发生的概率。
- 缺点:不能完全避免缓存雪崩,如果在某一时间段内,过期的缓存数量仍较多,数据库仍可能承受较大压力。而且对于一些需要精确过期控制的数据不太适用。
- 方案二:使用多级缓存
- 实现方式:构建多级缓存架构,如一级缓存使用Redis,二级缓存可以使用本地缓存(如Guava Cache)。当一级缓存失效时,先从二级缓存获取数据,如果二级缓存也没有则查询数据库。同时,更新缓存时先更新一级缓存,再更新二级缓存。
- 优点:多级缓存可以在一定程度上缓解数据库压力,即使一级缓存大量失效,二级缓存也能拦截部分请求。而且本地缓存的访问速度快,能提高系统整体响应速度。
- 缺点:增加了系统架构的复杂性,需要管理多级缓存的一致性。如果二级缓存数据更新不及时,可能会出现数据不一致问题。同时,本地缓存受内存限制,存储的数据量有限。
- 方案三:缓存高可用
- 实现方式:采用Redis集群(如Redis Sentinel或Redis Cluster)来提高Redis的可用性。如果某个节点发生故障,其他节点可以继续提供服务,减少因Redis服务故障导致缓存雪崩的风险。
- 优点:提高了Redis的可用性,能有效应对Redis单点故障问题,保障系统的稳定性。
- 缺点:增加了运维成本,需要管理和维护Redis集群。并且集群之间的数据同步可能存在延迟,可能会影响数据一致性。
- 方案一:设置随机过期时间