Redis面试题、知识点总结,一篇文章让Redis成为面试加分项

Redis面试题、知识点总结,一篇文章让Redis成为面试加分项

前言

参与了几次中大厂的面试,你会发现一面时对于八股文的考察也具有侧重点(MySQL=Redis > 网络 > 系统 >设计模式 > java集合> JVM >spring)

本文的目标就是通过这一篇文章让你能在面试时将Redis相关的问题回答漂亮。

所以整理问题时,本文会从一个问题出发(面试官会问),联想出更多问题(面试官可能会追问,也可以自己说:我还知道。。。)以求加分。(当你对一块知识了解的比较好时,就要想办法拉长这块内容的面试时长)

1.Redis基础

Redis了解吗?

Redis 是一种基于内存的数据库,对数据的读写操作都是在内存中完成,加上Redis对使用的数据结构做了优化,因此读写速度非常快,最常用于做缓存

[Redis基础联想1]:提到数据结构和缓存这两个关键字,尽量引出追问

[Redis基础联想2]: 为什么用 Redis 作为 MySQL 的缓存?:主要是因为 Redis 具备「高性能」和「高并发」两种特性

高性能是因为Redis是基于内存的,比直接使用MySQL在硬盘中读数据快很多。(提到MySQL可能会引出双写一致性问题)

高并发是指单台设备的Redis的QPS是MySQL的10倍,能到达10w+。

2.Redis数据结构

你知道哪些Redis的数据类型?

常见的有五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)、Zset(有序集合)

[数据类型联想1]:这些数据类型的应用场景有哪些?

  • String 类型的应用场景:缓存对象、常规计数、分布式锁、共享 session 信息等。
  • List 类型的应用场景:消息队列(但是有两个问题:1. 生产者需要自行实现全局唯一 ID;2. 不能以消费组形式消费数据)等。
  • Hash 类型:缓存对象、购物车等。
  • Set 类型:聚合计算(并集、交集、差集)场景,比如点赞、共同关注、抽奖活动等。
  • Zset 类型:排序场景,比如排行榜、电话和姓名排序等。

[数据类型联想2]:String底层数据结构知道吗?

SDS:简单动态字符串,是对c语言中char数组缺点的改进:

  • char数组不能保存二进制数据,因为其以’\n’作为字符串的结尾,而SDS使用整型数组保存数据,可以保存图片、视频等二进制数据。
  • char数组获取数组长度时间复杂度O(n),SDS维护一个len属性,做到了O(1)
  • char数组拼接字符串可能造成缓冲区溢出,SDS维护内存大小的属性,减去len属性就可以得到剩余可用内存检查是否够用,不够则扩容。

[数据类型联想3]:Zset底层数据结构知道吗?

答:压缩列表或跳表。

  • 如果有序集合的元素个数小于 128 个,并且每个元素的值小于 64 字节时,Redis 会使用压缩列表作为 Zset 类型的底层数据结构;
  • 如果有序集合的元素不满足上面的条件,Redis 会使用跳表作为 Zset 类型的底层数据结构;

在 Redis 7.0 中,压缩列表数据结构已经废弃了,交由 listpack 数据结构来实现了。

追问:压缩列表有什么问题,为什么废弃?

答:连锁更新,压缩列表每个节点会记录前一个节点的长度,记录这个长度默认需要一个字节,当一个字节保存不下时(超过254)会扩充到5个字节,当一个节点长度改变或插入节点时,可能会让下一个节点的记录长度扩充4个字节,使得整体长度变长,又可能导致下下一个节点长度改变,触发连锁反应,浪费资源。

再追问:那跳表了解吗?

跳表是一个可以快速查找的有序链表, 搜索、插入、删除操作的时间复杂度跟红黑树都是一样量级的均为O(logn)

再再最追问:那Redis为什么用跳表不用红黑树呢?

跳表不采用红黑树、平衡二叉树这类平衡树的原因主要有两点(答出两点就够了):

  • 在做范围查找的时候,跳表比平衡树操作要简单。在平衡树上,我们找到指定范围的小值之后,还需要以中序遍历的顺序继续寻找其它不超过大值的节点。如果不对平衡树进行一定的改造,这里的中序遍历并不容易实现。而在跳表上进行范围查找就非常简单,只需要在找到小值之后,对第 1 层链表进行若干步的遍历就可以实现。
  • 从算法实现难度上来比较,跳表比平衡树要简单得多。平衡树的插入和删除操作可能引发子树的调整,逻辑复杂,而跳表的插入和删除只需要修改相邻节点的指针,操作简单又快速。

3.Redis线程模型

Redis 是单线程吗?(经典)

我们常说Redis是单线程的是因为,Redis从接收请求到操作数据再到回复请求这个主要过程是有一个线程(主线程)完成的。

但是实际上Redis并不是单线程的,Redis有后台线程负责处理文件关闭,AOF刷盘,释放内存等耗时任务。

[Redis线程联想1]:Redis 采用单线程为什么还这么快?(经典追问)

有如下几个原因:

  • Redis 的大部分操作都在内存中完成,并且采用了高效的数据结构,因此 Redis 瓶颈可能是机器的内存或者网络带宽,而并非 CPU。(既然 CPU 不是瓶颈,那么自然就采用单线程的解决方案了)
  • Redis 采用单线程模型可以避免了多线程之间的竞争,省去了多线程切换带来的时间和性能上的开销,而且也不会导致死锁问题。
  • Redis 采用了 I/O 多路复用机制处理大量的客户端 Socket 请求,IO 多路复用机制是指一个线程处理多个 IO 流。(就是我们经常听到的 select/epoll 机制。简单来说,在 Redis 只运行单线程的情况下,该机制允许内核中,同时存在多个监听 Socket 和已连接 Socket。内核会一直监听这些 Socket 上的连接请求或数据请求。一旦有请求到达,就会交给 Redis 线程处理,这就实现了一个 Redis 线程处理多个 IO 流的效果。)

4.Redis持久化

Redis 如何实现数据不丢失?

为了保证内存中的数据不会丢失,Redis 实现了数据持久化的机制,这个机制会把数据存储到磁盘,这样在 Redis 重启就能够从磁盘中恢复原有的数据。

Redis 共有三种数据持久化的方式:

  • AOF 日志:每执行一条写操作命令,就把该命令以追加的方式写入到一个文件里;
  • RDB 快照:将某一时刻的内存数据,以二进制的方式写入磁盘;
  • 混合持久化方式:Redis 4.0 新增的方式,集成了 AOF 和 RBD 的优点;

[持久化联想1]: AOF 日志是如何实现的?

Redis 执行完一条写操作命令,然把该命令以追加的方式写入到一个文件里,然后 Redis 重启时,会读取该文件记录的命令,然后逐一执行命令的方式来进行数据恢复。

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

答“如果先将写操作命令记录到 AOF 日志里,再执行该命令的话,如果当前的命令语法有问题,那么如果不进行命令语法检查,该错误的命令记录到 AOF 日志里后,Redis 在使用日志恢复数据时,就可能会出错。

再追问:先执行命令后写入日志有什么问题吗?

  • 数据可能会丢失: 执行写操作命令和记录日志是两个过程,那当 Redis 在还没来得及将命令写入到硬盘时,服务器发生宕机了,这个数据就会有丢失的风险。
  • 可能阻塞其他操作: 由于写操作命令执行成功后才记录到 AOF 日志,所以不会阻塞当前命令的执行,但因为 AOF 日志也是在主线程中执行,所以当 Redis 把日志文件写入磁盘的时候,还是会阻塞后续的操作无法执行。

[持久化联想2]:AOF 日志过大,会触发什么机制?

会出发aof重写机制,AOF中可能有不再有用的命令,AOF 重写机制是在重写时,读取当前数据库中的所有键值对,然后将每一个键值对用一条命令记录到「新的 AOF 文件」,等到全部记录完后,就将新的 AOF 文件替换掉现有的 AOF 文件。

追问:重写的过程中,主进程修改了已经存在的key-value怎么办?

答:如果主进程修改了已经存在 key-value,那么会发生写时复制,此时这个 key-value 数据在子进程的内存数据就跟主进程的内存数据不一致了,为了解决这种数据不一致问题,Redis 设置了一个 AOF 重写缓冲区,当 Redis 执行完一个写命令之后,它会同时将这个写命令写入到 「AOF 缓冲区」和 「AOF 重写缓冲区」。当子进程完成 AOF 重写工作后,会向主进程发送一条信号,主进程收到该信号后,会调用一个信号处理函数,该函数主要做以下工作:

  • 将 AOF 重写缓冲区中的所有内容追加到新的 AOF 的文件中,使得新旧两个 AOF 文件所保存的数据库状态一致;
  • 新的 AOF 的文件进行改名,覆盖现有的 AOF 文件。

[持久化联想3]:RDB 快照是如何实现的呢?

一旦 AOF 日志非常多,势必会造成 Redis 的恢复操作缓慢。为了解决这个问题,Redis 增加了 RDB 快照。RDB 快照就是记录某一个瞬间的内存数据,在 Redis 恢复数据时,直接将 RDB 文件读入内存就可以。

追问:RDB 在执行快照的时候,数据能修改吗?

答:不推荐,但是可以的,执行 bgsave 过程中,Redis 依然可以继续处理操作命令的,也就是数据是能被修改的,关键的技术就在于**写时复制技术(Copy-On-Write, COW)。**如果主线程执行写操作,则被修改的数据会复制一份副本,然后 bgsave 子进程会把该副本数据写入 RDB 文件,在这个过程中,主线程仍然可以直接修改原来的数据。会造成数据不一致,是要等下一轮持久化执行时再去同步,如果redis突然宕机,就是会导致丢失部分最新数据的。

[持久化联想4]:Redis采用的是哪种方式?/为什么会有混合持久化?

RDB 优点是数据恢复速度快,但是快照的频率不好把握。频率太低,丢失的数据就会比较多,频率太高,就会影响性能。

AOF 优点是丢失数据少,但是数据恢复不快。

为了集成了两者的优点, Redis 4.0 提出了混合使用 AOF 日志和内存快照,也叫混合持久化,既保证了 Redis 重启速度,又降低数据丢失风险。混合持久化工作在 AOF 日志重写过程,当开启了混合持久化时,在 AOF 重写日志时,fork 出来的重写子进程会先将与主线程共享的内存数据以 RDB 方式写入到 AOF 文件,然后主线程处理的操作命令会被记录在重写缓冲区里,重写缓冲区里的增量命令会以 AOF 方式写入到 AOF 文件,写入完成后通知主进程将新的含有 RDB 格式和 AOF 格式的 AOF 文件替换旧的的 AOF 文件。

也就是说,使用了混合持久化,AOF 文件的前半部分是 RDB 格式的全量数据,后半部分是 AOF 格式的增量数据

追问:混合持久化有什么优缺点?

混合持久化优点:

  • 混合持久化结合了 RDB 和 AOF 持久化的优点,开头为 RDB 的格式,使得 Redis 可以更快的启动,同时结合 AOF 的优点,有减低了大量数据丢失的风险。

混合持久化缺点:

  • AOF 文件中添加了 RDB 格式的内容,使得 AOF 文件的可读性变得很差;
  • 兼容性差,如果开启混合持久化,那么此混合持久化 AOF 文件,就不能用在 Redis 4.0 之前版本了。

5.Redis集群

Redis 如何实现服务高可用?

要想设计一个高可用的 Redis 服务,一定要从 Redis 的多服务节点来考虑,比如 Redis 的主从复制、哨兵模式、切片集群。

[集群联想1]:主从复制是什么?

主从复制是 Redis 高可用服务的最基础的保证,实现方案就是将从前的一台 Redis 服务器,同步数据到多台从 Redis 服务器上,即一主多从的模式,且主从服务器之间采用的是「读写分离」的方式。

主服务器可以进行读写操作,当发生写操作时自动将写操作同步给从服务器,而从服务器一般是只读,并接受主服务器同步过来写操作命令,然后执行这条命令。注意,主从服务器之间的命令复制是异步进行的。所以,无法实现强一致性保证(主从数据时时刻刻保持一致),数据不一致是难以避免的。

[集群联想2]:哨兵模式了解吗?

在使用 Redis 主从服务的时候,会有一个问题,就是当 Redis 的主从服务器出现故障宕机时,需要手动进行恢复。

为了解决这个问题,Redis 增加了哨兵模式(Redis Sentinel),因为哨兵模式做到了可以监控主从服务器,并且提供主从节点故障转移的功能。

[集群联想3]:切片集群模式?当 Redis 缓存数据量大到一台服务器无法缓存用什么模式?

当 Redis 缓存数据量大到一台服务器无法缓存时,就需要使用 Redis 切片集群(Redis Cluster )方案,它将数据分布在不同的服务器上,以此来降低系统对单主节点的依赖,从而提高 Redis 服务的读写性能。

Redis Cluster 方案采用哈希槽(Hash Slot),来处理数据和节点之间的映射关系。在 Redis Cluster 方案中,一个切片集群共有 16384 个哈希槽,这些哈希槽类似于数据分区,每个键值对都会根据它的 key,被映射到一个哈希槽中,具体执行过程分为两大步:

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

哈希槽被自动平均或手动分配映射到各Redis节点上。

[集群联想4]:集群脑裂知道吗?

在 Redis 主从架构中,部署方式一般是「一主多从」,主节点提供写操作,从节点提供读操作。 如果主节点的网络突然发生了问题,哨兵发现主节点失联了,它就认为主节点挂了(但实际上主节点正常运行,只是网络出问题了),于是哨兵就会在「从节点」中选举出一个 leader 作为主节点,这时集群就有两个主节点了 —— 脑裂出现了

等网络恢复,旧主节点会降级为从节点,再与新主节点进行同步复制的时候,由于会从节点会清空自己的缓冲区,所以导致之前客户端写入的数据丢失了。

追问:那脑裂问题怎么解决呢?

答:当主节点发现从节点总数量小于阈值或者通信超时,那么禁止主节点进行写数据,直接把错误返回给客户端。等到新主库上线时,就只有新主库能接收和处理客户端请求,此时,新写的数据会被直接写到新主库中。而原主库会被哨兵降为从库,即使它的数据被清空了,也不会有新数据丢失。

6.Redis过期删除与内存淘汰策略

7.Redis缓存

8.其他常问

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/26198.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

收音机的原理笔记

1. 收音机原理 有线广播:我们听到的声音是通过空气振动进行传播,因此可以通过麦克风(话筒)将这种机械振动转换为电信号,传到远处,再重新通过扬声器(喇叭)转换为机械振动&#xff0c…

软件设计师笔记-程序语言基础知识

编程语言之间的翻译形式 编程语言之间的翻译形式主要有三种:汇编、解释和编译。这三种方式在将源代码转换为机器可执行的代码时,有着各自的特点和流程。 汇编: 定义:汇编是低级语言(如汇编语言)到机器语言的一种翻译方式。汇编语言是为特定计算机或计算机系列设计的一种…

PostgreSQL的视图pg_database

PostgreSQL的视图pg_database pg_database 是 PostgreSQL 中的一个系统视图,用于显示当前数据库集群中的所有数据库的信息。通过查询 pg_database 视图,数据库管理员可以获取关于每个数据库的详细信息,例如数据库的名称、所有者、编码、表空…

打造精细化运维新玩法(四)

二、SLO健康度——从0到1构建SLO 和大多互联网企业一样,蚂蚁的基础设施侧存在众多的异构系统,被上层的业务应用和服务所依赖。考虑到不同系统的技术栈、架构、部署等因素,我们需要找到一种通用的、泛化性强的数字化方案指导和构建基础设施域内…

智能楼宇可视化:赋能智慧园区管理

图扑智慧园区楼宇可视化系统,集成多种数据源,实现全方位监控与管理,提升园区的资源利用率和用户满意度,推动智能化管理进程。

豆瓣电影信息爬虫实战-2024年6月

豆瓣电影信息爬虫教程 摘要 本文将详细介绍如何使用Python编写一个爬虫程序,用于抓取豆瓣电影列表页面上的电影详细信息。通过本教程,你将学习到如何使用requests和PyQuery库来发送HTTP请求、解析HTML内容,并提取所需的数据。 目录 环境搭…

【机器学习】使用RetinaNet解决图像识别的正负样本失衡问题

1. 引言 1.1. 研究背景 正负样本失衡问题的表现和影响在目标检测任务中尤为显著,下面我将从多个方面更详细地阐述这一问题: 1.1.1.正负样本失衡的表现形式 样本数量差异显著: 在目标检测的数据集中,正样本(包含目标…

电线电缆单根燃烧试验 电缆垂直燃烧试验

电线电缆单根燃烧试验 电线电缆单根燃烧试验是一种用来评估电线电缆在受到火焰作用时的燃烧性能的测试方法。这种试验通常是将电线电缆垂直固定,然后使用特定的火焰源对其进行燃烧,以观察电线电缆的燃烧行为和燃烧速度。通过这个试验,可以评估…

护眼台灯哪个品牌好?几款性价比最高的护眼台灯推荐

在过去,科技尚未发展至如今这般先进水平时,晚上需要照明的时候,我们通常只能依赖白炽灯。尽管白炽灯以其低成本和接近自然光的显色性获得了一定的青睐,随着时代的发展,现在市面上出现了更为护眼的选择——LED台灯。然而…

一文介绍暗区突围手游 游戏特色、具体玩法和独特的玩法体验

🍉 CSDN 叶庭云:https://yetingyun.blog.csdn.net/ 《暗区突围》是一款由腾讯魔方工作室群开发的第一人称射击游戏,于 2022 年 7 月 13 日正式公测,支持 Android 和 iOS 平台。这款游戏以从虚构的暗区收集物资并安全撤离作为最终目…

OpenGauss数据库-7.用户及角色

第1关:创建用户 gsql -d postgres -U gaussdb -W passwd123123 CREATE USER jackson WITH PASSWORD jackson123; 第2关:修改用户 gsql -d postgres -U gaussdb -W passwd123123 ALTER USER jackson WITH PASSWORD Abcd123; 第3关:创建角色 …

【JVM】JVM 的内存区域

Java虚拟机(JVM)在执行Java程序时,将其运行时数据划分到若干不同的内存区域。这些内存区域的管理对Java应用程序的性能和稳定性有着重要影响。JVM的内存区域主要包括以下几部分: 方法区(Method Area)&#…

Qt实现简易播放器

效果如图 源码地址: 简易播放器: 基于Qt的简易播放器,底层采用VLC源码 - Gitee.com GitHub:GitHub - a-mo-xi-wei/easy-player: 基于Qt的调用VLC的API的简易播放器

Linux操作系统学习:day01

内容来自:Linux介绍 视频推荐:Linux基础入门教程-linux命令-vim-gcc/g -动态库/静态库 -makefile-gdb调试 day01 基础概念 Linux 是 UNIX 操作系统的一个克隆系统, 但是Linux是开源的。 Linux是一个基于文件的操作系统。操作系统需要和硬件进行交互…

【TensorFlow深度学习】使用TensorFlow实现双DQN与优先级经验回放

使用TensorFlow实现双DQN与优先级经验回放 使用TensorFlow实现双DQN与优先级经验回放:强化学习的高级策略探索双DQN算法简介优先级经验回放代码实现结语 使用TensorFlow实现双DQN与优先级经验回放:强化学习的高级策略探索 在深度强化学习领域&#xff0…

QQ音乐绿钻API接口:解锁更多音乐可能性

在我们日常生活中,音乐是不可或缺的一部分。无论是在上班途中,还是在健身房锻炼时,我们都可以通过听音乐来放松自己。然而,在现如今的音乐市场中,有时候我们会觉得收听的歌曲有限,想要尝试更多不同的音乐类…

《大道平渊》· 拾贰 —— 天下大事必作于细:做好每一件小事,必然大有所成!

《平渊》 拾贰 "天下难事必作于易,天下大事必作于细。" 社群一位大佬最近在研究新项目, 他做事的 "方法论" 令我深受启发。 他在测试项目时, 每一步都做的非常细致: 整个项目的测试都被划分为一件件小事, 然后有条不紊地推进…… …

代码随想录刷题笔记-哈希表篇

文章目录 242 有效的字母异位词(easy)力扣地址题目描述题目实例解题思路代码实现 383 赎金信(easy)力扣地址题目描述题目实例解题思路代码实现 49 字母异位词分组(mid)力扣地址题目描述题目实例解题思路代码实现 438 找到字符串中所有字母异位词(mid)力扣地址题目描述题目实例解…

【回溯】Leetcode 77. 组合【中等】

组合 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1: 输入: n 4, k 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ] 解题思路 定义递归函数&#xff1…

免费插件集-illustrator插件-Ai插件-文本属性批处理

文章目录 1.介绍2.安装3.通过窗口>扩展>知了插件4.功能解释5.总结 1.介绍 本文介绍一款免费插件,加强illustrator使用人员工作效率,进行文本属性批处理。首先从下载网址下载这款插件 https://download.csdn.net/download/m0_67316550/87890501&am…