Redis面试知识

1、Redis是单线程还是多线程呢?

  1. Redis不同版本之间采用的线程模型是不一样的,在Redis4.0版本之前使用的是单线程模型,在4.0版本之后增加了多线程的支持。在4.0之前虽然我们说Redis是单线程,也只是说它的网络I/O线程以及Set 和 Get操作是由一个线程完成的。但是Redis的持久化(如bgsave命令)、集群同步还是使用其他线程来完成。4.0之后添加了多线程的支持,主要是体现在大数据的异步删除功能上,例如 unlink key、flushdb async、flushall async 等

2、为什么Redis在4.0之前会选择使用单线程?而且使用单线程还那么快?

  1. Redis 的大部分操作都在内存中完成,内存中的执行效率本身就很快,并且采用了高效的数据结构,比如哈希表和跳表。
  2. 使用单线程避免了多线程的竞争,省去了多线程切换带来的时间和性能开销,并且不会出现死锁。
  3. 采用 I/O 多路复用机制处理大量客户端的Socket请求,因为这是基于非阻塞的 I/O 模型,这就让Redis可以高效地进行网络通信,I/O的读写流程也不再阻塞。

## 追加问点:描述一下哈希表和跳表这两种数据结构##

3、Redis是如何实现数据不丢失的呢?

  1. AOF 日志(Append Only File,文件追加方式):记录所有的操作命令,并以文本的形式追加到文件中。
  2. RDB 快照(Redis DataBase):将某一个时刻的内存数据,以二进制的方式写入磁盘。
  3. 混合持久化方式:Redis 4.0 新增了混合持久化的方式,集成了 RDB 和 AOF 的优点。

4、描述一下 AOF和 RDB的实现原理

  1. AOF采用的是写后日志的方式,Redis先执行命令把数据写入内存,然后再记录日志到文件中。AOF日志记录的是操作命令,不是实际的数据,如果采用AOF方法做故障恢复时需要将全量日志都执行一遍
  2. RDB采用的是内存快照的方式,它记录的是某一时刻的数据,而不是操作,所以采用RDB方法做故障恢复时只需要直接把RDB文件读入内存即可,实现快速恢复。

详细浏览这篇文章关于AOF和RDB以及关于这两种混合模式实现数据持久化操作

# 追加问点#:
Redis为什么要先执行命令,再把数据写入日志呢?

主要是由于Redis在写入日志之前,不对命令进行语法检查,所以只记录执行成功的命令,避免出现记录错误命令的情况,而且在命令执行后再写日志不会阻塞当前的写操作

引申问题:AOF采用的是 “写后日志” 的方式,为什么MySQL则采用的是 “写前日志”,好处是啥?
对比后面这点,就很明了了

后写日志又有什么风险呢?

  1. 数据可能会丢失:如果 Redis 刚执行完命令,此时发生故障宕机,会导致这条命令存在丢失的风险。
  2. 可能阻塞其他操作:AOF 日志其实也是在主线程中执行,所以当 Redis 把日志文件写入磁盘的时候,还是会阻塞后续的操作无法执行。

5、RDB做快照时会阻塞线程吗?

Redis 提供了两个命令来生成 RDB 快照文件,分别是 save 和 bgsave。save 命令在主线程中执行,会导致阻塞。而 bgsave 命令则会创建一个子进程,用于写入 RDB 文件的操作,避免了对主线程的阻塞,这也是 Redis RDB 的默认配置,在上个问题的链接中有关于这两个命令的详细介绍以及区别。

6、RDB 做快照的时候数据能修改吗?

save是同步的会阻塞客户端命令,bgsave的时候是可以修改的

7、Redis是怎么解决在bgsave做快照的时候允许数据修改呢?

主要是利用 bgsave的子线程实现的,具体操作如下:

  1. 如果主线程执行读操作,则主线程和 bgsave 子进程互相不影响;
  2. 如果主线程执行写操作,则被修改的数据会复制一份副本,然后 bgsave子进程会把该副本数据写入 RDB 文件,在这个过程中,主线程仍然可以直接修改原来的数据。
    在这里插入图片描述
  3. 注意的是:Redis 对 RDB 的执行频率非常重要,因为这会影响快照数据的完整性以及 Redis 的稳定性,所以在 Redis 4.0 后,增加了 AOF 和 RDB 混合的数据持久化机制: 把数据以 RDB 的方式写入文件,再将后续的操作命令以 AOF 的格式存入文件,既保证了 Redis 重启速度,又降低数据丢失风险。

8、Redis如何实现高可用吧?

主从复制、哨兵模式,以及 Redis 集群
主从复制:将从前的一台 Redis 服务器,同步数据到多台从 Redis 服务器上,即一主多从的模式,这个跟MySQL主从复制的原理一样
在这里插入图片描述
引申问题:既然说到MYSQL的主从复制,那你描述一下其原理

  1. master服务器将数据的改变记录二进制binlog日志,当master上的数据发生改变时,则将其改变写入二进制日志中
  2. slave服务器会在一定时间间隔内对master二进制日志进行探测其是否发生改变,如果发生改变,则开始一个I/OThread请求master二进制事件
  3. 同时主节点为每个I/O线程启动一个dump线程,用于向其发送二进制事件,并保存至从节点本地的中继日志中,从节点将启动SQL线程从中继日志中读取二进制日志,在本地重放,使得其数据和主节点的保持一致,最后I/OThread和SQLThread将进入睡眠状态,等待下一次被唤醒
  4. 也就是说:从库会生成两个线程,一个I/O线程,一个SQL线程;I/O线程会去请求主库的binlog,并将得到的binlog写到本地的relay-log(中继日志)文件中;主库会生成一个log dump线程,用来给从库I/O线程传binlog;SQL线程,会读取relay log文件中的日志,并解析成sql语句逐一执行;

既然你说mysql的主从复制原理是通过记录二进制binlog日志改变来做到的,那redis的主从复制也是一样的吗?描述一下其原理。

哨兵模式:使用 Redis 主从服务的时候,会有一个问题,就是当 Redis 的主从服务器出现故障宕机时,需要手动进行恢复,为了解决这个问题,Redis 增加了哨兵模式(因为哨兵模式做到了可以监控主从服务器,并且提供自动容灾恢复的功能)
在这里插入图片描述
Redis Cluster(集群): 是一种分布式去中心化的运行模式,是在 Redis 3.0 版本中推出的 Redis 集群方案,它将数据分布在不同的服务器上,以此来降低系统对单主节点的依赖,从而提高 Redis 服务的读写性能
在这里插入图片描述

9、使用哨兵模式在数据上有副本数据做保证,在可用性上又有哨兵监控,一旦master宕机会选举salve节点为master节点,这种已经满足了我们的生产环境需要,那为什么还需要使用集群模式呢?

哨兵模式归根节点还是主从模式,在主从模式下我们可以通过增加slave节点来扩展读并发能力,但是没办法扩展写能力和存储能力,存储能力只能是master节点能够承载的上限。所以为了扩展写能力和存储能力,我们就需要引入集群模式

10、集群中那么多Master节点,redis cluster在存储的时候如何确定选择哪个节点呢?

采用的是类一致性哈希算法实现节点选择的,Redis Cluster将自己分成了16384个Slot(槽位),哈希槽类似于数据分区,每个键值对都会根据它的 key,被映射到一个哈希槽中,具体执行过程分为两大步:

  1. 根据键值对的 key,按照 CRC16 算法计算一个 16 bit 的值
  2. 再用 16bit 值对 16384 取模,得到 0~16383 范围内的模数,每个模数代表一个相应编号的哈希槽

每个Redis节点负责处理一部分槽位,假如你有三个master节点 ABC,每个节点负责的槽位有对应如下:
在这里插入图片描述
这样实现了cluster节点的选择

在面试中,我们不懂的问题可以带过,或者把面试官往我们熟悉的领域引导,才能在面试中越战越强,遇到很厉害的面试官会深挖,所以,千万不要给自己挖坑,没有深入研究的名词就不要说了,免得自己跳进去。以上问题都还有很多可以引申、不足和深入的地方。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值