Redis在面试中有很大的概率会问到,因此我们一定要学会回答此方面的问题。 Redis主要涉及到使用场景已经一些其他方面的问题。
下面是有可能涉及到的问题。
问题一:你最近的项目中那些场景用到了Redis呢?
需要结合简历项目上的业务进行具体说明。该问题一是验证你项目场景的真实性,二是作为深入发问的切入点。
若是回答有关缓存的内容,那么接下来有可能就会问你有关缓存三兄弟(穿透、击穿、雪崩)、双写一致、持久化、数据过期策略、数据淘汰策略方面的问题。
若回答有关分布式锁的内容,那么下面就有可能问你setnx、redisson等。
若回答有关消息队列、延迟队列方面内容,那么接下来就有可能对采用何种数据类型进行提问。
所以可根据回答内容对有关方面进行强化。
问题二:如果发生了缓存穿透、击穿、雪崩,该如何解决?
1.缓存穿透
Redis缓存穿透是一个在缓存系统中常见的问题,它指的是当缓存和数据库中都不存在某个查询的数据时,大量的请求会直接穿透缓存层,直接访问数据库,导致数据库的压力骤增,甚至可能引发系统崩溃或拒绝服务(DoS)攻击。以下是关于Redis缓存穿透的详细分析:
Redis缓存穿透的原因
数据不存在:查询的数据在数据库中本身就不存在,每次查询都会直接访问数据库。
恶意攻击:攻击者故意查询大量不存在的数据,以绕过缓存层,直接对数据库造成压力。
业务逻辑问题:由于代码缺陷或数据异常,导致系统频繁查询不存在的数据。
Redis缓存穿透的解决方案
缓存空对象
原理:当数据库中查询的数据为空时,将空结果也缓存起来,并设置较短的过期时间。这样,在缓存有效期内,对于相同的查询请求,可以直接从缓存中返回空结果,避免对数据库的再次查询。
应用场景:适用于查询结果可能为空,且对实时性要求不高的场景。
布隆过滤器(Bloom Filter)
原理:布隆过滤器主要由一个很长的二进制向量(位数组)和一系列随机映射函数(哈希函数)组成。当需要存储一个元素时,该元素通过多个哈希函数计算出一系列位置,并将这些位置在二进制向量中对应的位设置为1。当需要查询一个元素是否存在于集合中时,也通过同样的哈希函数计算出位置,并检查这些位置上的位是否都为1。如果都为1,则认为该元素可能存在于集合中;如果有任何一个位置上的位不为1,则可以确定该元素一定不存在于集合中。在查询缓存之前,使用布隆过滤器过滤掉可能不存在于数据库中的请求。
缺点
存在误判率:由于哈希函数的碰撞问题,布隆过滤器在判断元素是否存在时存在一定的误判率。即,有可能将不存在的元素误判为存在。
无法删除元素:布隆过滤器中的元素一旦被添加,其对应的位就会被设置为1,之后无法再将这些位恢复为0,因此布隆过滤器不支持元素的删除操作。
应用场景:适用于查询数据量大,且对误判率有一定容忍度的场景。
2.缓存击穿
**缓存击穿(Cache Breakdown)给某一个key设置了过期时间,当key过期的时候,恰好这时间点对这个key有大量的并发请求过来,这些并发的请求可能会瞬间把DB压垮
解决方案:
互斥锁(Mutex Lock):在缓存失效后,第一个请求线程去查询数据库并重新构建缓存,其他线程则等待构建完成,然后直接从缓存中读取数据。这种方式可以减少对数据库的访问次数,但会增加线程等待时间。强一致性,但性能差
逻辑过期:逻辑过期是一种处理缓存数据失效时间的策略,与物理过期(即直接设置缓存项的过期时间)不同。在逻辑过期的方式中,缓存数据并不会在过期时被直接删除,而是会在缓存中保留该数据,但标记其为“过期”,表示该数据已经不再是最新的,或者已经不可用。高可用性,性能优,但不能保证数据绝对一致
3.缓存雪崩
缓存雪崩是指在缓存系统中,大量缓存key在同一时间失效或Redis服务宕机,导致大量请求直接到达数据库,造成后端系统的压力骤增,甚至引起系统崩溃的现象。
解决方案
1.给不同key的TTL添加随机值,设置随机的失效时间:为缓存对象设置稍微有差异的随机失效时间,避免大量缓存对象在同一时间失效。
2.利用Redis集群提高服务的可用性:如Redis哨兵模式或Redis集群部署方式,确保个别Redis节点下线时,整个缓存层依然可用。
哨兵模式实现原理
监控:哨兵节点定期向所有主节点和从节点发送PING命令,以检查它们的运行状态。
主观下线:如果哨兵节点在给定的时间内(通过sentinel down-after-milliseconds配置)未收到某个节点的有效响应,则将该节点标记为主观下线。
客观下线:当多个哨兵节点(达到配置的quorum值)都将某个主节点标记为主观下线时,该主节点被标记为客观下线。
故障转移:在主节点被标记为客观下线后,哨兵节点会进行故障转移操作,包括从所有健康的从节点中选举一个新的主节点,并将所有从节点切换到新的主节点上。
集群模式实现原理
数据分片:Redis Cluster将数据分为16384个槽(slot),每个节点可以处理0个或多个槽。
节点通信:节点之间通过Gossip协议进行通信,交换彼此的状态信息和槽的分配情况。
故障检测:节点之间会定期发送PING消息来检测对方是否在线。如果某个节点在一段时间内未收到其他节点的响应,则将该节点标记为疑似下线。当足够多的节点都认为某个节点已下线时,该节点被正式标记为已下线。
故障转移:当主节点下线时,集群中的从节点会进行选举,选举出一个新的主节点来接管原来的槽和数据。
3.给缓存业务添加降级限流策略:
降级可作为系统的保底策略,适用于穿透、击穿、雪崩
自动降级:系统可以根据一些关键数据进行自动降级,如CPU使用率、内存占用率、响应时间等。当这些指标超过预设的阈值时,系统可以自动关闭一些非核心服务或功能,以释放资源,保护核心服务。
人工降级:在某些情况下,如系统升级、维护或遇到严重错误时,管理员可以手动触发降级操作,以减少对系统的影响。
流量控制:通过设置系统的最大并发数,当请求超过这个数值时,系统可以拒绝新的请求或将其放入队列等待处理。通过限制单位时间内的请求数量,如每秒请求数(QPS),来防止系统被过量的请求压垮。
流量整形:通过平滑突发请求,将请求流量整形为稳定的流量,以避免系统资源的突然波动。
排队与请求:当请求超过系统处理能力时,可以将请求放入队列中等待处理。同时,可以设置合理的等待时间和超时时间,以避免用户长时间等待或系统资源被无效占用。
4.给业务添加多级缓存:虽然这会增加Redis的存储空间需求,但可以避免大量缓存同时失效的问题。
助记
《缓存三兄弟》
穿透无中生有key,布隆过滤null隔离。
缓存击穿过期key,锁与非期解难题。
雪崩大量过期key,过期时间要随机。
面试必考三兄弟,可用限流来保底。