Redis面试题面经整理+解析

前言

本文主要是针对Redis的高频知识点整理出来的面试题,答案大部分参考网上,仅供复习参考。本文中如果出现解答错误希望指出,共同进步,共同学习。

正文

Q1:你了解Redis,能介绍一下Redis吗?

Redis(全称:Remote Dictionary Server 远程字典服务)是一个开源的使用ANSIC语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,遵守BSD协议。是一个非关系型数据库(NoSQL)。


Q2:Redis与其他数据库有什么很大的优势吗?

  1. 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
  2. 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
  3. 事务 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,但是不保证原子性,即失败了的不影响其他成功的。通过MULTI和EXEC指令包起来。
  4. 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

Q3:Redis也有事务吗?能不能说一下Redis的事务?

Redis的事务本质就是一组命令的集合。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。Redis单个命令保证原子性,一个事务里面多个命令就不保证了,即有成功有失败。

Redis的事务只要分为三个阶段:开始事务,命令入队,执行事务。期间可以使用watch指令来对变量进行监控,watch类似乐观锁,如果watch监控的多个KEY中任何KEY的值已经被其他客户端更改,则使用EXEC执行事务时,事务队列将不会被执行,同时返回Nullmulti-bulk应答以通知调用者事务执行失败。


Q4:Redis有丰富的特性,那么特性有哪些?

速度快;简单稳定; 支持多种数据结构;支持多种编程语言;功能丰富;持久化;主从复制;高可用和分布式。好了,下面的问题基本也是围绕这八个特性来问的。


Q5:Redis为什么速度那么快?

总结一句:Redis 使用了单线程架构和 IO 多路复用模型来实现高性能的内存数据库服务。

扩展开来:① Redis使用纯内存访问,将所有数据放在内存中。② 非阻塞 IO,Redis 使用 epoll 作为 IO 多路复用技术的实现,再加上 Redis 本身的事件处理模型将 epoll 中的连接、读写、关闭都转换为事件,不在网络 IO 上浪费过多的时间。③ 单线程避免了线程切换和竞争产生的消耗。单线程的一个问题是对于每个命令的执行时间是有要求的,如果某个命令执行时间过长会造成其他命令的阻塞,对于 Redis 这种高性能服务来说是致命的,因此 Redis 是面向快速执行场景的数据库。

补充:Redis的单线程指的是网络请求模块使用了一个线程(所以不需考虑并发安全性),即一个线程处理所有网络请求,其他模块仍用了多个线程。


Q6:为什么说Redis简单稳定呢?是因为单线程吗?

与单线程是有一定的关系的。之所以说Redis简单稳定,主要是有三个方面的原因:

① 源码很少,早期只有 2 万行左右,在 3.0 版本由于添加了集群特性,增加到了 5 万行左右,相对于很多 NoSQL 数据库来说代码量要少很多。

② 采用单线程模型,使得服务端处理模型更简单,也使客户端开发更简单。

③ 不依赖底层操作系统的类库,自己实现了事件处理的相关功能。


Q7:说一下Redis支持哪些数据类型,分别可以运用到什么场景?


Q8:Redis功能丰富,那么提供了哪些简单的功能?

① 提供了键过期功能,可以实现缓存。

② 提供了发布订阅功能,可以实现消息系统。

③ 支持 Lua 脚本,可以创造新的 Redis 命令。

④ 提供了简单的事务功能,能在一定程度上保证事务特性。

⑤ 提供了流水线功能,客户端能将一批命令一次性传到 Redis,减少网络开销。


Q9:Redis是怎么进行持久化?

我们知道Redis的数据都存在内存里,如果突然宕机,数据就会全部丢失,因此必须有一种机制来保证Redis的数据不会因为故障而丢失,这种机制就是Redis的持久化机制。

Redis的持久化机制主要是有两种,第一种是RDB快照,第二种是AOF日志。如果我们的服务器开启了AOF持久化功能,那么服务器会优先使用AOF文件来还原数据库的状态。只有在AOF持久化功能处于关闭的状态的时候,服务器才能使用RDB文件来还原数据库状态。


Q10:能说一下RDB持久化的原理吗?

RDB持久化是通过快照来实现的,在指定的时间间隔内将内存的数据集快照写入磁盘,恢复的时候就是将快照文件读取到内存中。

(1)一般手动触发可以使用save和bgsave命令:

save:阻塞当前 Redis 服务器,直到 RDB 过程完成为止,对于内存比较大的实例会造成长时间阻塞,不建议使用。

bgasve:Redis 进程执行 fork 操作创建子进程,RDB 持久化过程由子进程负责,完成后自动结束。阻塞只发生在 fork 阶段,一般时间很短。bgsave 是针对 save 阻塞问题做的优化,因此 Redis 内部所有涉及 RDB 的操作都采用 bgsave 的方式,而 save 方式已经废弃。所以RDB持久化主要原理要从bgsave这个命令来讲。(见下一题)

(补充:可能会问到为什么需要fork一个子进程?这是因为Redis是单线程的,内存快照又要要求Redis进行文件IO操作。所以我们fork一个子进程就可以保证Redis主进程不进行IO操作,可以更好的保持极高的性能。)

(2)而其他一些通过其他命令也会被动触发RDB持久化的也有:

FLUSHALL:清空命令也会触发持久化操作,但dump.rdb文件中是空的,无意义;

SHUTDOWN :关闭数据库命令也会触发redis持久化操作 ,前提是没有开启AOF持久化;

DEBUG RELAOD:用该命令重新加载Redis时,也会自动触发save操作;

(3)然后还有就是通过配置文件配置redis.conf文件中可以设置save。


Q11:那能讲一下bgsave具体的工作流程吗?

① 执行 bgsave 命令,Redis 父进程判断当前是否存在正在执行的子进程,如 RDB/AOF 子进程,如果存在 bgsave 命令直接返回。

② 父进程执行 fork 操作创建子进程,fork 操作过程中父进程会阻塞。

③ 父进程 fork 完成后,bgsave 命令返回并不再阻塞父进程,可以继续响应其他命令。

④ 子进程创建 RDB 文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换。

⑤ 进程发送信号给父进程表示完成,父进程更新统计信息。

在这里详细说一下第三个步骤里面父进程fork一个子进程之后父进程还要持续服务端的请求。然后对内存数据结构进行不间断的修改。那我们不可能对同一片内存进行操作,所以用到了写入时复制(copy on write机制)。在父进程需要后续再写指令的时候,复制一个内存页面处理新的写请求,而子进程的页面是没有变化的,所以这也被称为快照的原因。

img


Q12:说了挺多你能总结一下RDB到底有什么优缺点?

优点:

  • 对数据的完整性要求不高
  • 因为主进程不进行任何的IO操作,所以对数据的大规模恢复有着极高的性能,适合全量恢复 ,备份等场景

缺点:

  • fork进程的时候,会占用一定的内存空间
  • 需要一定的时间间隔来进行操作,如果redis意外宕机了,那么最后一次修改的数据就没有了

Q13:能说一下AOF持久化的原理吗?

AOF 持久化以独立日志的方式记录每次写命令,重启时再重新执行 AOF 文件中的命令达到恢复数据的目的。AOF 的主要作用是解决了数据持久化的实时性,目前是 Redis 持久化的主流方式。

默认是不开启AOF的,如果开启了,则优先使用AOF!

AOF的具体工作流程如下:

  1. 命令的实时写入,调用到命令
  2. 所有的写入命令追加到aof_buf(缓冲区)中
  3. AOF缓冲区根据对应的策略向硬盘做同步操作
  4. 随着AOF文件越来越大,需要定期对AOF文件进行重写,压缩,父进程执行fork创建子进程,由子进程根据内存快照执行AOF重写,父进行继续响应后面的命令并写入aof_rewrite_buf(重写缓冲区),在子进程完成重写后,重写缓冲区再把新增的写入命令写入到新的AOF文件中。(注意,父进程原本的任务是没有终止的,还是会进行原来而AOF文件的写入同步)
  5. Redis服务重启,加载AOF文件进行数据恢复

img

主动触发可以使用bgrewriteaof命令,被动触发需要修改配置文件两个参数auto-aof-rewrite-min-sizeauto-aof-rewrite-percentage 来确定自动触发时机。


Q14:AOF缓冲区,和AOF重写缓冲区,两者有什么区别?而且缓冲区有哪些对硬盘操作的同步的策略?

aof缓冲区:是正常使用aof作为数据落地中间地带,所有的数据先到aof缓冲区再到aof文件中。

aof重写缓冲区:是aof触发重写机制时,redis还要继续接收数据,这个数据就写到aof重写缓冲区,当aof重写ok时,主进程在把aof重写缓冲区的数据写到新的aof文件,然后替换原来的。

aof缓冲区同步策略,通过参数appendfsync控制,具体有三个配值

选项的值 说明 其他
always 命令写入aof_buf后调用系统fsync操作同步到AOF文件,fsync完成后线程返回 每次写入都要同步AOF文件,在一般的SATA硬盘很难达到高性能
everysec 命令写入aof_buf后调用系统write操作,write完成后线程返回。fsync同步操作由线程每秒调用一次(建议策略) 默认同步策略
no 命令写入aof_buf后调用系统write操作,不对AOF文件做fsync同步,同步硬盘操作由操作系统负责,通常同步周期最长30秒 操作系统每次同步AOF文件的周期不可控,而且会加大每次同步硬盘的数据量,虽然提升了性能,但数据安全性无法保证

Q15:说了这么多重写机制,那为什们重写就可以把我们的AOF文件变小?

  • 重写的时候,进程内已经超时的数据不再写入文件
  • 旧的AOF文件含有无效命令,重写使用进程内数据直接生成,新的AOF文件只保留最终数据的写入命令
  • 多条写命令可以合并为一个,为了防止溢出,以64个元素为界拆分为多条

待更新

posted @ 2020-08-13 18:48  CryFace  阅读(1302)  评论(0编辑  收藏  举报