面试题答案
一键面试缓存雪崩
原理
缓存雪崩是指在同一时间大量的缓存过期失效,导致大量请求直接打到数据库,造成数据库压力过大甚至崩溃。
实现步骤
- 设置不同过期时间:避免大量缓存同时过期。可以在设置缓存过期时间时,在原过期时间基础上增加一个随机值,比如原过期时间为60分钟,随机值范围为0 - 10分钟,这样缓存过期时间就在60 - 70分钟之间,分散了过期时间。
- 使用二级缓存:一级缓存设置较短过期时间,二级缓存设置较长过期时间。当一级缓存失效时,先从二级缓存获取数据,避免直接查询数据库。如果二级缓存也没有,查询数据库后更新一级和二级缓存。
Redis数据结构和命令
使用SET key value EX seconds
命令设置缓存,通过seconds
指定不同的过期时间。
缓存穿透
原理
缓存穿透是指查询一个不存在的数据,由于缓存没有命中,每次都会去查询数据库,若恶意发起大量这种查询,会导致数据库压力过大。
实现步骤
- 布隆过滤器:在查询数据前,先通过布隆过滤器判断数据是否存在。布隆过滤器可以判断一个元素一定不存在或者可能存在。如果布隆过滤器判断不存在,则直接返回,不会查询数据库。
- 空值缓存:当查询数据库发现数据不存在时,也将空值缓存起来,并设置较短的过期时间,下次查询同样的数据直接从缓存返回空值,避免再次查询数据库。
Redis数据结构和命令
布隆过滤器可使用Redis的BITMAP
数据结构模拟实现。例如使用SETBIT key offset value
设置布隆过滤器的位,GETBIT key offset
获取位的值。空值缓存使用SET key "" EX seconds
设置空值缓存。
缓存击穿
原理
缓存击穿是指一个热点Key,在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候对DB的压力会瞬时增大。
实现步骤
- 互斥锁:在查询缓存失效时,先获取一个互斥锁(例如使用Redis的
SETNX key value
命令,成功获取锁返回1,失败返回0),只有获取到锁的请求才能查询数据库并更新缓存,其他请求等待。获取锁的请求更新完缓存后释放锁(DEL key
),其他等待的请求重新查询缓存。 - 永不过期:对于热点数据,设置永不过期(
SET key value
不设置过期时间),并在数据更新时主动更新缓存。
Redis数据结构和命令
使用SETNX
获取互斥锁,DEL
释放互斥锁。对于永不过期的缓存设置,直接使用SET key value
命令。
数据最终一致性
原理
在分布式系统中,由于数据同步存在延迟,很难做到强一致性,但可以保证最终一致性。通过异步更新机制,在数据发生变化时,将变化记录下来,通过异步任务逐步将变化同步到各个节点的缓存中。
实现步骤
- 消息队列:使用消息队列(如Kafka)来接收数据变化的消息。当数据在数据库中更新时,同时发送一条消息到消息队列。
- 消费端:消息队列的消费端监听队列,接收到消息后,根据消息内容更新Redis缓存。这样即使有延迟,最终各个节点的缓存也会被更新为最新数据。
Redis数据结构和命令
根据具体业务需求,可能会使用到SET
、HSET
等命令更新Redis缓存。
系统高可用性
原理
通过多节点部署、数据复制和故障转移机制来保证系统在部分节点出现故障时仍能正常运行。
实现步骤
- Redis Cluster:采用Redis Cluster集群模式,将数据分布在多个节点上,每个节点负责一部分数据。当某个节点出现故障时,集群会自动将该节点的槽位(数据分片)迁移到其他节点,保证数据的可用性。
- Sentinel:使用Redis Sentinel机制,对Redis主从节点进行监控。当主节点出现故障时,Sentinel会自动选举一个从节点成为新的主节点,保证系统的持续运行。
Redis数据结构和命令
在Redis Cluster模式下,数据的读写操作和普通Redis操作类似,只是数据会自动分布到不同节点。Sentinel通过SENTINEL monitor master_name ip port quorum
等命令配置对主节点的监控。