百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

关于 Redis 缓存最常见的10道面试真题,不看答案你能拿下几道题?

wptr33 2024-12-22 21:13 93 浏览

文章首将对应问题罗列,可以根据目录找到感兴趣的

  • AOF 为什么直接采用文本协议
  • AOF 为什么把命令追加到 aop_buf 中
  • Redis 实现分布式锁的方式有几种?最好的是哪一种
  • Redis 中的 CAS 操作
  • Redis 中的 String 数据结构底层实现
  • Redis 中的 Key 过期机制
  • Redis 中的 从节点会出发过期策略么
  • 结合项目中使用的 Redis 客户端说一下序列化的方式
  • 为什么 Redis 是单线程的
  • Redis 是单线程的(基于主线程),为什么这么快

AOF 为什么直接采用文本协议

文本协议具有很好的兼容性。开启 AOF 后,所有的写命令都包含追加操作,直接开启协议格式,避免二次处理开销。文本协议具有可读性,方便直接修改和处理

AOF 为什么把命令追加到 aop_buf 中

redis 使用单线程响应命令,如果每次写 AOF 文件命令都直接追加到硬盘,那么性能完全取自当前硬盘的负载。写入缓冲区的另一个好处是 redis 可以提供多种缓冲区同步硬盘的策略,在性能和安全性方面做出平衡

Redis 实现分布式锁的方式有几种?最好的是哪一种

有很多种;常用的是根据 set 的一个组合命令以及使用使用 lua 脚本控制的分布式锁。redisson 则是功能比较强大的一种以 java 语言实现的操作 redis 客户端,其中锁的实现还包括公平锁、联锁、红锁、读写锁等,分布式锁也是基于 lua 脚本实现的,由于是基于底层封装,业务短调取只有一行加锁的代码。

redisson 客户端的分布式锁实现了可重入性,set 组合命令需要开发

没有最好的实现,只有最适合项目的实现,如果项目并发量不高,自己实现 lua 脚本控制即可;如若对分布式锁功能要求高,可以考虑引用 redisson 实现

Redis 中的 CAS 操作

watch 指令在 redis 事物中提供了 CAS 的行为

为了检测被 watch 的 keys 在是否有多个 clients 同时改变引起冲突,这些 keys 将会被监控。如果至少有一个被监控的 key 在执行 exec 命令前被修改,整个事物将会回滚,不执行任何动作,从而保证原子性操作,并且执行 exec 会得到 null 的回复

Redis 中的 String 数据结构底层实现

字符串基于一种 SDS(简单动态字符串),其结构包括 T capacity(数组容量)、T len(数组长度)、byte flags(特殊标志位)、byte[] content(数组内容);redis 的字符串有两种存储结构,在长度特别短时,使用的时 embstr,而当内容长度超过 44 字节时,使用 raw 存储

为什么超过 44 字节使用 raw?

内存分配器 tcmalloc 等分配内存大小都是 2/4/8/16/32/64 字节等,为了能容纳一个完整的 embstr 对象,最少会分配 32 字节的空间,如果字符串再稍微长一些,那就是 64 字节。如果字符串超过了 64 字节,就会使用 raw 存储。SDS 结构体中占据了 19 字节,content 中字符串是以字节 NULL 结尾的【之所以多出这样一个字节,是便于 glibc 的字符串处理函数,方便调试打印输出】所以最大容纳字符串长度是 44 字节

SDS 结构使用了范性 T,为什么不直接用 int 呢?

因为当字符串比较短时,len 和 capacity 可以直接使用 byte 和 short 来表现,Redis 为了对内存做极致的优化,不用长度的字符串使用不同的结构体来表示。Redis 规定字符串的长度不得超过 512MB,创建字符串时,len 和 capacity 一样长,因为大多数场景下,不会使用 append 修改字符串

Redis 中的 Key 过期机制

redis 有 3 种 key 过期机制:惰性删除,定期删除,当前已用内存超过 maxmemory 限定时,触发主动清理策略

redis 会为每个设置了过期时间的 key 放入一个独立的字典中,默认是每秒进行 10 次定期扫描,扫描过程中不会扫描过期字典中所有的 key,而是采用了一种贪心策略:

  1. 从过期字典中随机选出 20 个 key
  2. 删除这 20 个 key 中已经过期的 key
  3. 如果过期的 key 的比例超过 1/4,重复步骤 1

同时,为了保证扫描过程不会出现循环过度,导致线程卡死的情况,算法加了扫描时间的上线,默认不会超过 25ms(控制每秒扫描多少次是由配置文件中的 hz 来决定,如果 hz 改为 100,则一秒内最少扫描 2000 个 key;另一方面,如果过期 key 比率超过 25%,则扫描 key 的个数无上限,但是 cpu 时间每秒钟最多占用 250ms)

redis 会持续扫描过去字典(循环多次),直到过期字典的 key 变的稀疏,才会停止,这样会导致线上读写请求出现明显的卡顿现象。导致这种卡顿现象的另外一种原因是内存管理器需要频繁回收内存页,这样也会产生一定的 CPU 消耗

客户端请求来到时,服务器正好进入定期扫描状态,客户端的请求将会等待至少 25ms 后才会进行处理,如果客户端将超时时间设置的比较短,那么就会出现大量的链接因为超时而关闭;如果有大批 key 过期,要给 key 过期时间设置一个随机范围

Redis 中的 从节点会出发过期策略么

从节点不会进行过期扫描,从节点对过期的处理是被动的。主节点在 key 到期时,会在 AOF 文件里增加一条 del 指令,同步所有从节点,从节点通过执行 AOP 的 del 指令来进行删除过期的 key

因为指令同步是异步进行的,所以如果祝节点过期的 key 的 del 指令没有及时同步从节点的话,就会出现主从不同步的情况

结合项目中使用的 Redis 客户端说一下序列化的方式

项目中使用的是 JedisCluster 客户端,使用 set 命令进行举例,set 指令具有两种插入方式;一种为 key 与 value 皆为 String,一种两者都是 byte[]。如果使用的是 set 一个 string 类型的 value,JedisCluster 在执行期间会调用 String 类的序列化方式进行序列化为二进制数组

另一种为在 set 指令操作前将 key、value 进行显式序列化,在项目中采取的方式为 key 调用.getBytes()方法,value 采用的是 ObjectOutputStream、ByteArrayOutputStream 进行序列化

为什么 Redis 是单线程的

Redis 是基于内存的操作,CPU 不是 Redis 的瓶颈,Redis 的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且 CPU 不会成为瓶颈,那就顺理成章地采用单线程的方案了

毕竟采用多线程会有很多麻烦,虽然后面高版本也支持了多线程

Redis 是单线程的(基于主线程),为什么这么快

完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于 HashMap,HashMap 的优势就是查找和操作的时间复杂度都是 O(1)

数据结构简单,对数据操作也简单,Redis 中的数据结构是专门进行设计的

采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗

使用多路 I/O 复用模型,非阻塞 IO;这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程

使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis 直接自己构建了 VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求

作者:龙台的技术笔记

原文链接:https://blog.csdn.net/qq_37781649/article/details/111415315

相关推荐

oracle数据导入导出_oracle数据导入导出工具

关于oracle的数据导入导出,这个功能的使用场景,一般是换服务环境,把原先的oracle数据导入到另外一台oracle数据库,或者导出备份使用。只不过oracle的导入导出命令不好记忆,稍稍有点复杂...

继续学习Python中的while true/break语句

上次讲到if语句的用法,大家在微信公众号问了小编很多问题,那么小编在这几种解决一下,1.else和elif是子模块,不能单独使用2.一个if语句中可以包括很多个elif语句,但结尾只能有一个else解...

python continue和break的区别_python中break语句和continue语句的区别

python中循环语句经常会使用continue和break,那么这2者的区别是?continue是跳出本次循环,进行下一次循环;break是跳出整个循环;例如:...

简单学Python——关键字6——break和continue

Python退出循环,有break语句和continue语句两种实现方式。break语句和continue语句的区别:break语句作用是终止循环。continue语句作用是跳出本轮循环,继续下一次循...

2-1,0基础学Python之 break退出循环、 continue继续循环 多重循

用for循环或者while循环时,如果要在循环体内直接退出循环,可以使用break语句。比如计算1至100的整数和,我们用while来实现:sum=0x=1whileTrue...

Python 中 break 和 continue 傻傻分不清

大家好啊,我是大田。今天分享一下break和continue在代码中的执行效果是什么,进一步区分出二者的区别。一、continue例1:当小明3岁时不打印年龄,其余年龄正常循环打印。可以看...

python中的流程控制语句:continue、break 和 return使用方法

Python中,continue、break和return是控制流程的关键语句,用于在循环或函数中提前退出或跳过某些操作。它们的用途和区别如下:1.continue(跳过当前循环的剩余部分,进...

L017:continue和break - 教程文案

continue和break在Python中,continue和break是用于控制循环(如for和while)执行流程的关键字,它们的作用如下:1.continue:跳过当前迭代,...

作为前端开发者,你都经历过怎样的面试?

已经裸辞1个月了,最近开始投简历找工作,遇到各种各样的面试,今天分享一下。其实在职的时候也做过面试官,面试官时,感觉自己问的问题很难区分候选人的能力,最好的办法就是看看候选人的github上的代码仓库...

面试被问 const 是否不可变?这样回答才显功底

作为前端开发者,我在学习ES6特性时,总被const的"善变"搞得一头雾水——为什么用const声明的数组还能push元素?为什么基本类型赋值就会报错?直到翻遍MDN文档、对着内存图反...

2023金九银十必看前端面试题!2w字精品!

导文2023金九银十必看前端面试题!金九银十黄金期来了想要跳槽的小伙伴快来看啊CSS1.请解释CSS的盒模型是什么,并描述其组成部分。答案:CSS的盒模型是用于布局和定位元素的概念。它由内容区域...

前端面试总结_前端面试题整理

记得当时大二的时候,看到实验室的学长学姐忙于各种春招,有些收获了大厂offer,有些还在苦苦面试,其实那时候的心里还蛮忐忑的,不知道自己大三的时候会是什么样的一个水平,所以从19年的寒假放完,大二下学...

由浅入深,66条JavaScript面试知识点(七)

作者:JakeZhang转发链接:https://juejin.im/post/5ef8377f6fb9a07e693a6061目录由浅入深,66条JavaScript面试知识点(一)由浅入深,66...

2024前端面试真题之—VUE篇_前端面试题vue2020及答案

添加图片注释,不超过140字(可选)1.vue的生命周期有哪些及每个生命周期做了什么?beforeCreate是newVue()之后触发的第一个钩子,在当前阶段data、methods、com...

今年最常见的前端面试题,你会做几道?

在面试或招聘前端开发人员时,期望、现实和需求之间总是存在着巨大差距。面试其实是一个交流想法的地方,挑战人们的思考方式,并客观地分析给定的问题。可以通过面试了解人们如何做出决策,了解一个人对技术和解决问...