一、Redis使用场景之缓存
1.面试官:在Redis中,缓存击穿如何理解?有没有解决方式?
候选人:给某一个key设置了过期时间,当key过期的时候,恰好这个时间点对这个key有大量的并发请求过来,这个并发请求可能会瞬间把DB压垮
解决方式:①互斥锁,强一致性,性能较差
②逻辑过期,高可用,性能优,但不能保证数据绝对一致
2.面试官:那什么是缓存雪崩?又该如何解决呢?
候选人:缓存雪崩是指在同一时间段大量的缓存key同时失效或Redis服务宕机,导致大量请求到达数据,带来巨大压力。
解决方式:①给不同key的TTL添加随机值
②利用Redis集群提高服务的可用性
③给缓存业务添加降级限流策略(nginx或SpringGateway)
④给业务添加多级缓存
3.面试官:Redis作为缓存,MySql的数据如何与Redis进行同步(双写一致性)?
候选人:(前提需要介绍自己的业务背景)
①允许延时一致的业务,采用异步通知
a.使用MQ中间件,更新数据之后,通知缓存删除
b.使用canal中间件,不需要修改业务代码,伪装mysql的一个从节点,canal通过读取binlog数据更新缓存
②强一致性的,采用Redisson提供的读写锁
a.共享锁:读锁readLock,加锁之后其他线程可以共享读操作
b.排它锁:也叫独占锁writeLock,加锁后阻塞其他线程读写操作
4.面试官:Redis作为缓存,数据的持久化是怎么做的?
候选人:有两种方式①RDB,也被叫做Redis数据快照
②AOF(默认关闭),开启后,可根据实际选用适当的配置项
RDB与AOF各有自己的优缺点,在实际开发中,往往结合二者来使用。
5.面试官:假如Redis的key过期后,会立即删除吗?
Redis对数据设置数据的有效时间,数据过期以后,就需要将数据从内存中删除掉,可以按照不同的规则进行删除,这种删除规则被称之为数据的删除策略(数据过期策略)。
候选人:在Redis中提供了两种数据过期策略:
第一种是惰性删除,在设置该key的过期时间后,不去管它,当需要该key时,检查它是否过期,如果过期就删除该key,反之则返回该key;
第二种是定期删除,就是每隔一段时间就对一些key进行检查。删除里面过期的key。
定期删除有两种方式:
①SLOW模式是定时任务,执行频率默认10HZ,每次不超过25ms,以通过修改配置文件redis.conf的hz选项来调整这个次数。
②FAST模式执行频率不固定,每次事件循环会尝试执行,但两次间隔不低于2ms,每次耗时不超过1ms。
Redis过期策略:惰性删除+定期删除配合使用。
6.面试官:Redis的数据淘汰策略有哪些?
数据淘汰策略:当Redis中的内存不够用时,此时向Redis中添加新的key,Redis会按照某一种规则将内存中的数据删除掉,这种数据的删除规则称为数据淘汰策略。
候选人:Redis支持8中不同的策略来选择要删除key:
a.noeviction:不淘汰任何key,但是内存满时不允许写入新数据,默认策略。
b.volatile-ttl:对设置了TTL的key,比较key的剩余TTL的值,TTL越小越先被淘汰。
c.allkeys-random:对全体key,随机进行淘汰。
d.volatile-random:对设置了TTL的key,随机进行淘汰。
e.allkeys-lru:对全体key,基于LRU算法进行淘汰。
f.volatile-lru:对设置了TTL的key,基于LRU算法进行淘汰。
g.allkeys-lfu:对全体key,基于LFU算法进行淘汰。
h.volatile-lfu:对设置了TTL的key,基于LFU算法进行淘汰。
①:LRU(Least Recently Used)最近最少使用。用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高。
②:LFU(Least Frequently Used)最少频率使用。会统计每个key的访问频率,值越小淘汰优先级越高。
二、Redis使用场景之分布式锁
1.Redis实现分布式锁主要利用Redis的setnx命令。
2.redisson实现分布式锁示例代码(加锁、设置过期时间等都是基于lua脚本(保证原子性)完成)
public void redisLock() throws InterruptedException {
//获取锁(重入锁),执行锁的名称
RLock lock = redissonClient.getLock("xxxlock");
//尝试获取锁,参数分别是:获取锁的最大等待时间(期间会重试),锁自动释放时间,时间单位
boolean isLock = lock.tryLock(10,30,TimeUnit.SECONDS);
//判断是否获取成功
if (isLock) {
try {
System.out.println("执行业务代码");
} finally {
//释放锁
lock.unlock();
}
}
}
3.面试官:Redisson实现分布式锁如何合理的控制锁的有效时长?
候选人:在redisson的分布式锁中,提供了一个WatchDog(看门狗),一个线程获取锁成功以后,WatchDog会给持有锁的线程续期(默认是每隔十秒续期一次)。
4.面试官:Redisson的这个锁,可以重入吗?
候选人:可以重入,多个锁重入需要判断是否是当前线程,在redis中进行存储的时候使用的hash结构,来存储线程信息和重入的次数。
5.面试官:redisson实现的分布式锁能解决主从一致性问题吗?
候选人:不能,但是可能利用redisson提供的红锁来解决此问题,需要注意的是,使用了红锁就会降低性能,并且运维维护成本也会变高,如果非要强一致性,建议使用zookeeper实现的分布式锁。
三、Redis使用场景之其他问题
1.面试官:Redis是单线程的,为什么还那么快?
候选人:①完全基于内存的,C语言编写;
②采用单线程,避免不必要的上下文切换;
③使用多路I/O复用模型,飞阻塞I/O。
2.面试官:Redis集群有哪些方案?
候选人:在Redis中提供的集群方案有三种:主从复制、哨兵模式、Redis分片集群。
3.面试官:介绍一下主从同步吧
候选人:单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,可以搭建主从集群,实现读写分离。一般都是一主多从,主节点负责写数据,从节点负责读数据,主节点写入数据后,需要把数据同步到从节点。