redis常见面试题(绝对干货)

 使用场景   
缓存  穿透 击穿 雪崩    双写一致 持久化 数据过期 淘汰策略
分布式锁  setnx redisson  
计数器
保存token     |
消息队列        |       数据类型
延迟队列        |

其他面试题
集群      主从   哨兵    集群  
事务
redis为什么这么快   


使用场景面试题
1.哪些场景中使用到了redis呢?
缓存    缓存三兄弟(穿透 击穿 雪崩) 双写一致 ,持久化,数据过期策略 ,数据淘汰策略 
分布式锁     setnx  redisson
消息队列 延迟队列    何种数据类型

2.如果发生了缓存 穿透 击穿 雪崩 该如何解决呢?
正常流程 根据主键查询    先查询redis 找到了 返回结果  redis查不到 查询数据库 DB查询到结果后 返回(返回之前先存储到redis)

缓存穿透:查询一个不存在的数据 MySQL查询不到数据也不会直接写入缓存 就会导致每次请求都查数据量
解决方案一 :缓存空数据 查询返回的数据为空  仍把这个空结果进行缓存
优点  :简单
缺点:消耗内存 可能会发生不一致的问题
解决方案二:布隆过滤器(查询不存在直接返回)
缓存预热时 预热布隆过滤器
优点 :内存占用较少 没有多余的key
缺点:实现复杂 ,存在误判

布隆过滤器主要是用于检索一个元素是否在一个集合中。我们当时使用的是redisson实现的布隆过滤布。
它的底层主要是先去初始化一个比较大数组,里面存放的二进制0或1。在一开始都是0,当一个key来了之后经过3次hash计算,
模于数组长度找到数据的下标然后把数组中原来的0改为1,这样的话,三个数组的位置就能标明一个key的存在。查找的过程也是一样的。

缓存击穿:给某一个key设置了过期时间,当key过期时候 恰好这个时间点对这个key有大量的并发请求过来,这些并发请求可能瞬间把DB压垮
解决方案一:互斥锁
当缓存失效时,不立即去load db,先使用如 Redis 的 setnx 去设置一个互斥锁,当操作成功返回时再进行load db的操作并回设缓存,否则重试get缓存的方法
解决方案二:逻辑过期
1.在设置key的时候,设置一个过期时间字段一块存入缓存中,不给当前key设置过期时间
2.当查询的时候,从redis取出数据后判断时间是否过期
3.如果过期则开通另外一个线程进行数据同步,当前线程正常返回数据,这个数据不是最新

缓存击穿的意思是对于设置了过期时间的key,缓存在某个时间点过期的时候,恰好这时间点对这个Key有大量的并发请求过来,
这些请求发现缓存过期一般都会从后端 DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把 DB 压垮。

如果选择数据的强一致性,建议使用分布式锁的方案,性能上可能没那么高,锁需要等,也有可能生死锁的问题
如果选择key的逻辑删除,则优先考虑的高可用性,性能比较高,但是数据同步这块做不到强一致。

缓存雪崩
是指在同一时段大量的缓存key同时失效或者redis服务宕机,导致大量请求到达数据库,带来巨大的压力。
解决方案
给不同的key的TTL(生存时间)添加随机值
利用redis集群提高服务的可用性
给缓存业务添加降级限流策略
给业务添加多级缓存

《缓存三兄弟》
穿透无中生有key,布隆过滤null隔离。
缓存击穿过期key,锁与非期解难题。
雪崩大量过期key,过期时间要随机。
面试必考三兄弟,可用限流来保底。

redis做为缓存,MySQL的数据如何与redis进行同步呢?(双写一致)
该问题要根据业务回答 先介绍业务背景 在根据业务背景进行回答
一致性要求高:采用Redisson提供的读写锁
1.共享锁:读锁readLock,加锁之后,其他线程可以共享读操作
2.排他锁:独占锁writeLock也叫,加锁之后,阻塞其他线程读写操作
允许延迟一致: 采用异步通知
1.使用MQ中间中间件,更新数据之后,通知缓存删除
2.利用canal中间件,不需要修改业务代码,伪装为mysql的一个从节点,canal通过读取binlog数据更新缓存

redis 持久化
RDB全称Redis Database Backup file(Redis数据备份文件),也被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。
当Redis实例故障重启后,从磁盘读取快照文件,恢复数据
AOF全程为Append Only File(追加文件) redis处理的每一个命令都会记录在AOF文件,可以看作是命令日志文件。

redis 对数据删除策略 
惰性删除:设置该key过期时间后,我们不去管它,当需要key时,我们在检查其是否过期 ,如果过期,我们就删掉它,反之返回该key
优点:对CPU友好,只会在使用该key时才会进行过期检查,对于很多用不到的key不用浪费时间进行过期检查
缺点:对内存不友好,如果一个key已经过期,但是一直没有使用,那么该key就会一直存在内存中,内存永远不会释放

定期删除
每隔一段时间 对key进行检查 删除里面过期的key(SLOW模式定时任务 默认10HZ+FAST模式)

redis的过期删除策略:惰性删除+定期删除 两种策略进行配合使用

假如缓存过多内存有限 怎么处理?(数据淘汰策略)
1.Redis提供了8种不同的数据淘汰策略,默认是noeviction不删除任何数据,内存不足直接报错
2.LRU:最少最近使用。用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高。
3.LFU:最少频率使用。会统计每个key的访问频率,值越小淘汰优先级越高

平时开发过程中用的比较多的就是allkeys-lru(结合自己的业务场景)


redis分布式锁
解决线程的互斥性

redis分布式锁,是如何实现的?
先按照自己简历上的业务进行描述分布式锁使用的场景
我们当使用的redisson实现的分布式锁,底层是setnx和lua脚本(保证原子性)

Redisson实现分布式锁如何合理的控制锁的有效时长?
在redisson的分布式锁中,提供了一个WatchDog(看门狗)一个线程获取锁成功以后
WatchDog会给持有锁的线程续期(默认是每隔10秒续期一次)

Redisson的这个锁,可以重入吗?
可以重入,多个锁重入需要判断是否是当前线程,在redis中进行存储的时候使用的hash结构来存储线程信息和重入的次数

Redisson锁能解决主从数据一致的问题吗
不能解决,但是可以使用redisson提供的红锁来解决,但是这样的话,性能就太低了、如果业务中非要保证数据的强一致性,
建议采用zookeeper实现的分布式锁

介绍一下redis的主从同步
单节点redis的并发能力是有上限的, 需要进一步提高redis的并发能力,就需要搭建主从集群,实现读写分离。
一般都是一注多从,主节点负责写数据,从节点负责读数据

能说一下,主从同步数据的流程
全量同步:
1.从节点请求主节点同步数据
2.主节点判断是否是第一次请求,是第一次就与从节点同步版本信息
3.主节点执行bgsave,生成rdb文件后,发送给节点去执行
4.在rdb生成执行期间。主节点会以命令的方式记录到缓冲区(一个日志文件)
5.把生成之后的命令日志文件发送给从节点进行同步

增量同步:
1.从节点请求主节点同步数据,主节点判断不是第一次请求,不是第一次就获取从节点的offset值
2.主节点从命令日志中获取offset值之后的数据, 发送给从节点进行数据同步

怎么保证redis的高并发高可用

哨兵模式:实现主从集群的自动故障恢复(监控 自动故障恢复 通知)

你们使用 redis是单点还是集群,那种集群?
主从(一主一从)+哨兵就可以了。单节点不超过10G内存,如果redis内存不足则可以给不同服务分配独立的redis主从节点

redis集群脑裂 该怎么解决呢?
集群脑裂是由于主节点和从节点和sentinel(哨兵) 处于不同的网络分区,使得哨兵没有能够心跳感知到主节点,所以通过选举的方式
提升了一个从节点为主节点,这样就存在了两个master,就像大脑分裂了一样,这样会导致客户端还在老的主节点那里写入数据,新节点
无法同步数据,当网络恢复后,哨兵 会将老的节点将为从节点,这时再从新master同步数据,就会导致数据丢失
解决:我们可以修改redis的配置,可以设置最少的从节点的数量以及缩短主从数据同步的延迟时间,达不到要求就拒绝请求,就可以避免
大量数据的丢失

主从解决高并发的问题  哨兵解决高可用的问题

分片集群结构

主从和哨兵可以解决高可用,高并发读的问题。但是依然有两个问题没有解决:
海量数据存储问题
高并发写问题
使用分片集群可以解决上述问题,分片集群特征:
redis的分片集群有什么作用?
集群中有多个master,每个master保存不同数据
每个master都可以有多个slave节点
master之间通过ping检测彼此健康状态
客户端请求可以 访问集群任意节点,最终都会被转发到正确节点

redis 分片集群中数据是怎么存储的和怎么读取的?
redis分片集群引入哈希槽的概念 redis集群有16384个哈希槽
将16384个哈希槽分配到不同的实力
读写数据:根据key的有效部分计算哈希值,对16354取余(有效部分,如果key前面有大括号,大括号的内容就是有效部分,如果没有,则以key本身做为有效部分)
余数作为插槽,寻找插槽所在的实例


redis是单线程的,但是为什么还那么快
1.redis纯内存操作,执行速度非常快
2.采用单线程,避免不必要的上下文切换可竞争条件,多线程还要考虑线程安全问题
3.使用I/O多路服用模型 非阻塞IO

能解释一下I/O多路复用模型?
redis是纯内存操作,执行速度非常快,它的性能瓶颈是网络延迟 而不是执行速度,I/O多路复用模型主要就是实现了高效的网络请求
用户空间和内核空间
常见的IO 模型
阻塞IO
非阻塞IO
IO的多路复用
redis 的网络模型

1.I/O多路复用
是指利用单个线程来同时监听多个Socket,并在某个Socket可读,可写时得到通知,从而避免无效的等待,充分利用cpu资源。
目前的I/O多路复用都是采用epoll模式实现 ,它会在通知用户Socket就绪的同时,把已就绪的socket写入用户空间,不需要挨个
遍历Socket来判断是否就绪,提升了性能。

2.redis网络模型
就是使用I/O多路复用结合事件的处理器来应对多个socket请求
连接应答处理器
命令回复处理器,在redis6.0之后,为了提升更好的性能,使用了多线程来处理回复事件
命令请求处理器,在redis6.0之后,将命令的转换使用了多个线程,增加命令转换速度,在命令执行的时候,依然是单线程


 

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值