面试题答案
一键面试缓存穿透
- 定义:指查询一个一定不存在的数据,由于缓存中没有,每次都会去数据库查询,若恶意攻击频繁查询不存在的数据,会导致数据库压力过大甚至崩溃。
- 对系统性能影响:大量请求绕过缓存直接访问数据库,使数据库负载剧增,可能导致数据库响应缓慢甚至宕机,影响整个系统的可用性。
- 解决方案
- 布隆过滤器
- 原理:布隆过滤器是一个很长的二进制向量和一系列随机映射函数。当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。查询时,元素通过相同的散列函数映射,若对应位置不全为1,则元素一定不在集合中;若全为1,大概率在集合中。这样可快速判断数据是否存在,若不存在则直接返回,不查询数据库。
- 注意事项:存在误判率,即可能把不存在的数据误判为存在;布隆过滤器需要占用一定内存空间,需根据预估数据量合理设置参数;数据变动时,如删除数据,布隆过滤器维护较复杂,通常采用定期重建或使用计数布隆过滤器等方式。
- 缓存空值
- 原理:当查询数据库发现数据不存在时,也将空值缓存起来,并设置较短过期时间。下次查询同样数据时,先从缓存获取,若为空则直接返回,避免多次查询数据库。
- 注意事项:空值缓存可能占用额外缓存空间;设置的过期时间需合理,过短则无法有效防止穿透,过长则可能影响新数据写入。
- 布隆过滤器
缓存雪崩
- 定义:指在某一时刻,大量缓存数据同时过期失效,导致大量请求直接访问数据库,使数据库瞬间压力过大,甚至崩溃。
- 对系统性能影响:如同雪崩一样,大量请求突然压向数据库,数据库可能无法承受巨大负载,造成系统响应时间延长、服务不可用等问题。
- 解决方案
- 随机过期时间
- 原理:在设置缓存过期时间时,不采用固定过期时间,而是在一个合理范围内随机设置过期时间,使缓存过期时间分散开,避免大量缓存同时过期。
- 注意事项:需合理设置随机范围,若范围过小,仍可能出现部分缓存集中过期;若范围过大,可能导致部分数据长时间占用缓存资源。
- 加锁排队
- 原理:当缓存失效时,使用分布式锁(如Redis的SETNX命令实现),只有获取到锁的请求才能查询数据库并更新缓存,其他请求等待。这样可以保证同一时间只有一个请求访问数据库,避免大量请求同时涌入。
- 注意事项:加锁可能导致系统并发性能下降;锁的释放要确保可靠,避免死锁情况;若持有锁的请求处理时间过长,其他请求等待时间也会过长,影响用户体验。
- 多级缓存
- 原理:构建多级缓存架构,如一级缓存采用内存缓存(如Redis),二级缓存采用本地缓存(如Guava Cache)。当一级缓存失效时,先从二级缓存获取数据,若二级缓存也没有,再查询数据库。这样可以在一定程度上减轻数据库压力。
- 注意事项:多级缓存增加了系统复杂度,需要处理好各级缓存之间的一致性问题;本地缓存存在内存限制,需合理设置缓存容量。
- 随机过期时间
缓存击穿
- 定义:指一个热点数据在缓存过期的瞬间,大量并发请求同时查询该数据,由于此时缓存失效,这些请求会同时访问数据库,可能使数据库压力骤增。
- 对系统性能影响:瞬间大量请求集中访问数据库,可能导致数据库响应变慢甚至挂掉,影响依赖该数据的业务功能正常运行。
- 解决方案
- 互斥锁
- 原理:与缓存雪崩中加锁排队类似,在缓存失效时,使用互斥锁(如分布式锁),只允许一个请求去查询数据库并更新缓存,其他请求等待。当第一个请求更新完缓存后,释放锁,其他请求从缓存获取数据。
- 注意事项:同样存在加锁导致并发性能下降问题;要注意锁的粒度,避免锁争用过于激烈;锁的获取和释放要保证原子性和可靠性。
- 永不过期
- 原理:对于热点数据不设置过期时间,或者设置一个超长的过期时间。同时,通过异步任务(如定时任务)或者数据变更监听机制,在数据发生变化时主动更新缓存。
- 注意事项:缓存数据可能长时间占用内存资源,需定期清理或根据业务情况优化缓存数据结构;异步更新缓存时要确保数据一致性,防止出现脏数据。
- 互斥锁