5面试题--redis

慢查询⽇志:⽤于记录执⾏时间超过给定时⻓的命令请求,⽤户可以通过这个功能产⽣的⽇志来监视和 优化查询速度。
布隆过滤器:⼆进制数组进⾏存储,若判断元素存在则可能实际存在,若判断不存在则⼀定不存在。

redis中incr、incrby、decr、decrby属于string数据结构,它们是原⼦性递增或递减操作:

incr 递增1并返回递增后的结果;
incrby 根据指定值做递增或递减操作并返回递增或递减后的结果(incrby递增或递减取决于传⼊值的
正负);
decr 递减1并返回递减后的结果;
decrby 根据指定值做递增或递减操作并返回递增或递减后的结果(decrby递增或递减取决于传⼊值
的正负);

Redis为什么这么快?

完全基于内存,绝⼤部分请求是纯粹的内存操作,⾮常快速;
数据结构简单,对数据操作也简单;
采⽤单线程,避免了不必要的上下⽂切换和竞争条件,也不存在多进程或者多线程导致的切换⽽消
耗 CPU,不⽤考虑各种锁的问题,不存在加锁和释放锁操作。CPU不是Redis的瓶颈,Redis的瓶
颈最有可能是机器内存的⼤⼩或者⽹络带宽;
使⽤多路I/O复⽤模型,⾮阻塞IO;

6.1 基本数据结构(底层实现)

键:字符串对象
值:字符串对象、列表对象、哈希对象、集合对象、有序集合对象

SDS

Redis底层使⽤SDS(简单动态字符串)替代C字符串原因:

1. 常数复杂度获取字符串⻓度。因为有 len 属性记录字符串⻓度(不计算最后⼀个空字符)
2. 杜绝了缓冲区溢出的可能性。因为有 free 属性记录未⽤空间⻓度,并当空间不⾜时 SDS API ⾃动扩容。
3. ⼆进制安全,可存⼊⽂本或者⼆进制数据。所有 SDS API 都会以处理⼆进制的⽅式来处理 SDS 存放在 buf 数组⾥的元素,程序不会对其中的数据做任何限制、过滤或者假设,数据在写⼊时是什么样的,它被读取时就是什么样。因为 SDS 使⽤ len 属性的值⽽不是空字符来判断字符串是否结
束。

SDS 空间预分配:

1. 如果对 SDS 进⾏修改后,SDS 的⻓度(即 len 值)将⼩于 1MB,那么程序分配和 len 属性同样⼤⼩的未使⽤空间,这时 SDS len 属性的值将和 free 属性的值相同。举个例⼦,如果修改后 SDS 的 len 将变成 13 字节,那么程序也会分配 13 字节的未使⽤空间,SDS 的 buf 数组的实际⻓度将变成 13+13+1=27 字节
2. 如果对 SDS 进⾏修改后,SDS 的⻓度将⼤于等于 1MB,那么程序会分配 1MB 的未使⽤空间。举个例⼦,如果修改后,SDS 的 len 将变成 30MB,那么 SDS 的 buf 数组的实际⻓度将为
30MB+1MB+1byte.

惰性空间释放:

⽤于优化 SDS 字符缩短操作,当缩短 SDS 字符串时,并不⽴即使⽤内存重分配来回收缩后多出来的字节,⽽是使⽤ free 属性将这些字节的数量记录下来,并等待将来使⽤。
特性:
1. 双向⽆环,链表头尾均有⼀个指针指向空
2. O(1) 时间复杂度获取表头指针、表尾指针和链表⻓度
3. 多态:链表节点使⽤ void* 指针来保持节点值,并且可以通过 list 结构的 dup(复制)、free(释放)、match(对⽐)三个属性为节点值设置类型特定函数,所以链表可以⽤于保存各种不同类型的值

字典

Redis 的字典使⽤ 哈希表 作为底层实现,⼀个哈希表⾥⾯可以有多个哈希表节点,⽽每个节点就保存了字典中的⼀个键值对。

哈希表结构

type 属性和 privdata 属性是针对不同类型的键值对,为创建多态字典⽽设置的。type 属性是⼀个指 向 dictType 结构的指针,每个 dictType 结构保存了⼀簇⽤于操作特定类型键值对的函数,Redis 会为 ⽤途不同的字典设置不同的类型特定函数。privdata 属性则保存了需要传给那些类型特定函数的可选参 数。
ht 属性是⼀个包含两个项的数组,数组中的每个项都是⼀个 dictht 哈希表,⼀般情况下,字典只使⽤ht[0] 哈希表,ht[1] 哈希表只会在对 ht[0] 哈希表进⾏ rehash 时使⽤。另⼀个与 rehash 有关的属性就是 rehashidx,它记录了 rehash ⽬前的进度,如果⽬前没有在进⾏ rehash,那么它的值为 -1。
计算索引:利⽤哈希算法计算哈希值,然后将哈希值与哈希⼤⼩掩码取与运算,得到索引下标。
解决冲突:链地址法,且每次添加到链表表头。
rehash ⽅式:为字典的 ht[1] 哈希表分配空间,这个哈希表的空间⼤⼩取决于要执⾏的操作和 ht[0] 当前包含的键值对数量。当执⾏扩展操作时,ht[1] 的⼤⼩为第⼀个⼤于等于 ht[0].used * 2 的 2^n;当执⾏收缩操作时,ht[1] 的⼤⼩为第⼀个⼤于等于 ht[0].used 的 2^n。之后将 ht[0] 上的所有键值对rehash 到 ht[1] 上。最后释放 ht[0],将 ht[1] 设置为 ht[0],并在 ht[1] 新创建⼀个空⽩哈希表,为下⼀次rehash 做准备。注意 rehash 操作是 渐进式的,即在执⾏增加、删除、查找或更新操作的时候同步进⾏ rehash 操作(trehashidx 记录索引),直到所有 rehash 完成,则置 -1。同时新增加的会加⼊到 ht[1],且外部查找时先查 ht[0],再查 ht[1]。
负载因⼦ = 哈希表已有节点数量 / 哈希表⼤⼩
扩展操作需满⾜:当没有创建当前服务的⼦进程时,负载因⼦⼤于等于 1;当创建当前服务的⼦进程时,负载因⼦⼤于等于 5。因为⼤多数操作系统都采⽤写时复制技术来优化⼦进程的使⽤效率,所以在 ⼦进程存在期间,服务器会提⾼执⾏扩展操作所需的负载因⼦,从⽽尽可能避免在⼦进程存在期间进⾏ 哈希表扩展操作,可以避免不必要的内存写⼊操作,最⼤限度地节约内存。 收缩操作需满⾜:负载因⼦⼩于 0.1。

跳跃表

跳跃表是⼀种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从⽽达到快速访问节点的⽬的。在⼤部分情况下,跳跃表的效率可以和平衡树相媲美,并且跳跃表的实现⽐平衡树更简单。跳跃表是作为有序集合键的底层实现之⼀。
其中每个节点层⾼(最⼤层⾼ level)是 1——32 随机⽣成的,length 是除表头外节点的数量。每个节点有层属性(前进指针和跨度)、后退指针、分值(⽤来排序)和成员对象(唯⼀存在)四部分,其中表头节点不使⽤后⾯三部分但是有。

整数集合

集合中不包含任何重复的元素,且数组中的元素按升序排列。数组中元素的真实类型由 encoding 决定。当有更⼤⻓度的元素时将发⽣(类型)升级,整数集合不⽀持降级。

压缩列表

当⼀个哈希键只包含少量键值对,并且每个键值对的键和值要么是⼩整数值,要么是⻓度⽐较短的字符串时,Redis 就会⽤压缩列表来做哈希键的底层实现。
压缩列表是 Redis 为了节约内存 ⽽开发的,是由 连续内存块 组成的顺序型数据结构。⼀个压缩列表可以包含任意多个节点,每个节点保存⼀个字节数组或者⼀个整数值。

压缩列表节点 的第⼀部分是上⼀个节点的⻓度(⽤于由当前位置计算得到上⼀个节点的位置),第⼆部分是当前节点的类型和⻓度,第三部分是当前节点的内容。由于第⼀部分会根据上个节点的⻓度动态确定存储位数⼤⼩,因此当插⼊或删除节点时可能(只有当连续多个⼤字节节点存在时)会出现连锁更新,但是其⼏率较低。

6.2 对象

共五类,包含字符串对象、列表对象、哈希对象、集合对象和有序集合对象。
实现了引⽤计数、对象共享(通过引⽤计数实现)、最后访问时间记录(当内存占⽤超过阈值将⾃动回收空转时间⻓的对象)等信息。

 字符串对象

其中 raw 即为 SDS,⽽ embstr 是 SDS 的改版(核⼼结构⼀样),仅需⼀次内存分配(SDS 需要两次:创建 RedisObject 和 SDS 对象),且创建的对象是在连续内存内,更好利⽤缓存。

  列表对象

列表对象的编码可以是 ziplist 或者 linkedlist。
当列表对象可以同时满⾜以下两个条件时,列表对象使⽤ ziplist 编码:
1. 列表对象保存的所有字符串元素的⻓度都⼩于 64 字节
2. 列表对象保存的元素数量⼩于 512 个
不能满⾜这两个条件的列表对象需要使⽤ linkedlist 编码

哈希对象

哈希对象的编码可以是 ziplist 或者 hashtable。
ziplist 编码的哈希对象使⽤压缩列表作为底层实现,当有新键值对要加⼊时,依次放⼊键和值。
hashtable 编码的哈希对象使⽤字典作为底层实现,哈希对象中的每个键值对都是⽤⼀个字典键值对来保存。 对于使⽤何种编码,与列表对象的两条规则类似。

集合对象 set

集合对象的编码可以是 intset 或者 hashtable(值设置为NULL)。
当集合对象中的所有元素都是整数且数量不超过 512 时,使⽤ intset 编码实现。

有序集合对象 zset

有序集合的编码可以是 ziplist 或者 skiplist。
ziplist 内的集合元素按分值从⼩到⼤进⾏排序。
skiplist 编码的有序集合对象使⽤ zset 结构作为底层实现,⼀个 zet 结构同时包含⼀个字典和⼀个跳跃表。zset 结构中的跳跃表按分值从⼩到⼤保存了所有集合元素,每个跳跃表节点都保存了⼀个集合元素,通过跳跃表,程序可以对有序集合进⾏ 范围型操作。此外,zset 结构中的 dict 字典为有序集合创建了⼀个从成员到分值的映射,字典中的每个键值对都保存了⼀个集合元素:字典的键保存了元素的成员,⽽字典的值则保存了元素的分值。
有序集合每个元素的成员都是⼀个字符串对象,⽽每个元素的分值都是⼀个 double 类型的浮点数。虽然 zset 结构同时使⽤了跳跃表和字典来保存有序集合元素,但这两种数据结构都会 通过指针来共享 相同元素的成员和分值,因此不会浪费额外的内存。
当有序集合对象同时满⾜以下两个条件时,对象使⽤ ziplist 编码:
1. 有序集合保存的元素数量⼩于 128 个;
2. 有序集合保存的所有元素成员的⻓度都⼩于 64 字节;
不满⾜任意⼀个条件,有序集合对象将使⽤ skiplist 编码。

6.3 数据库

服务器默认创建 16 个数据库,客户端默认连接第⼀个数据库(0 号数据库)。
SELECT 命令切换数据库原理:修改 redisClient.db 指针,指向⽬标数据库。
每个数据库对象中包含 字典属性(所有键值对) 和 过期字典属性(设置过期时间的键值对) 等。
过期键删除策略:
1. 惰性删除:所有读写数据库的命令前都将进⾏过期键检测,若过期则删除否则继续执⾏;
2. 定期删除:在规定时间内,分多次遍历服务器中的各个服务器,并从过期字段属性中随机检查指定。
数量的键是否过期,并删除过期键。

RDB 持久化

Redis 是内存数据库,数据库状态存储在内存⾥,可通过 RDB 持久化将数据库状态保存到 RDB ⽂件 (⼆进制⽂件,保存键值对)中。 SAVE、BGSAVE 都是保存 RDB ⽂件的命令,后者 fork ⼦线程达到可边保存边执⾏其他命令的不阻塞处理。RDB ⽂件载⼊是在服务器启动时⾃动执⾏的,没有相关命令。因为 AOF ⽂件的更新频率通常⽐RDB ⽂件的更新频率⾼,所以如果服务器开启了 AOF 持久化功能,那么服务器会优先使⽤ AOF ⽂件 来还原数据库状态。只有在 AOF 持久化功能处于关闭状态时,服务器才会使⽤ RDB ⽂件来还原数据库状态。
间隔性数据保存实现原理:利⽤ BGSAVE 命令,通过设置每隔多少时间⾄少保存多少次,会⾃动
(100ms)检查是否满⾜保存条件并进⾏保存操作。(记录了已保存次数以及上次保存的时间戳)

RDB ⽂件结构:

1. 标明这是⼀个 RDB ⽂件
2. 数据库版本号
3. 数据库键值对内容(若为空数据库则⽆该字段),可以保存任意多个⾮空数据库
4. 数据库状态结束符
5. 校验和字段
其中 每个⾮空数据库 在 RDB ⽂件中都可以保存为如下三个部分:
1. ⻓度 1 字节,当读⼊程序遇到这个值的时候,它知道接下来将读⼊的是⼀个数据库号码
2. 保存数据库号码,⻓度不定。当程序读⼊ db_number 部分之后,服务器会调⽤ SELECT 命令,根据读⼊的数据库号码进⾏数据库切换,使得之后读⼊的键值对可以载⼊到正确的数据库中
3. 保存数据库中所有键值对数据,如果键值对带有过期时间,那么过期时间也会和键值对保存在⼀
起。

AOF 持久化

与 RDB 持久化通过保存数据库中的键值对来记录数据库状态不同,AOF 持久化是通过保存 Redis 服务器所执⾏的写命令来记录数据库状态的。
AOF 持久化功能的实现可以分为:
1. 命令追加:服务器在执⾏完⼀个写命令之后,会把写命令追加到服务器状态的 AOF 缓存区的末尾
2. ⽂件写⼊与同步,默认值为下图的 everysec
AOF ⽂件载⼊:(使⽤伪客户端是因为写命令只能通过客户端向服务端发送)

AOF ⽂件重写:

实际并不需要对现有的 AOF ⽂件进⾏任何读取、分析或者写⼊操作,这个功能是通过读取服务器当前的数据库状态来实现的。为了防⽌在重写的过程中数据库状态发⽣改变从⽽数据不⼀致,服务器需要执⾏以下三个⼯作:
执⾏客户端发来的命令;
将执⾏后的写命令追加到 AOF 缓冲区;
将执⾏后的写命令追加到 AOF 重写缓冲区。

RDB与AOF区别

RDB可以理解为是⼀种全量数据更新机制,AOF可以理解为是⼀种增量的更新机制,AOF重写可以理解为是⼀种全量+增量的更新机制(第⼀次是全量,后⾯都是增量)
RDB适合服务器数据库数据量⼩,写命令频繁的场景
AOF适合数据量⼤,写命令少的场景
AOF重写适合在AOF运⾏了很久的写命令之后执⾏。

数据淘汰策略

Redis 内存数据集⼤⼩上升到⼀定⼤⼩的时候,就会进⾏数据淘汰策略。
volatile-lru:从已设置过期时间的数据集中挑选最近最少使⽤的数据淘汰。
volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。
volatile-random:从已设置过期时间的数据集中任意选择数据淘汰。
volatile-lfu 从设置过期时间的数据集(server.db[i].expires)中挑选出使⽤频率最⼩的数据淘汰。
没有设置过期时间的key不会被淘汰,这样就可以在增加内存空间的同时保证需要持久化的数据不
会丢失
no-enviction:当内存达到限制的时候,不淘汰任何数据,不可写⼊任何数据集,所有引起申请内存的命令会报错。
allkeys-lru:从数据集中挑选最近最少使⽤的数据淘汰。
allkeys-random:当内存达到限制的时候,从数据集中任意选择数据淘汰。
allkeys-lfu 从数据集(server.db[i].dict)中挑选使⽤频率最⼩的数据淘汰,该策略要淘汰的key⾯
向的是全体key集合,⽽⾮过期的key集合。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

231128 刷题日报

值班刷题的第二天,早上地铁上看了一道题,以为很简单 LCR 019. 验证回文串 II 我的思路是引入计数器左右指针,然而 Leetcode老哥提醒了我: 你看看这个字符串“lcuxxucul”,你的默认优先删除左边,但是删除…

SystemVerilog 入门

文章目录 包定义SystemVerilog 数据类型结构体 SystemVerilog 过程块可嵌套模块接口 System Verilog 的优点 提高了硬件建模能力、编码效率和抽象能力;RTL 级、系统级行为描述; 增强了验证能力和为大规模复杂设计编写有效、无竞争测试程序的断言功能&am…

ESP32-Web-Server 实战编程-使用文件系统建立强大的 web 系统

ESP32-Web-Server 实战编程-使用文件系统建立强大的 web 系统 概述 在前述章节我们讲述了在网页端控制多个 GPIO 的案例。当程序开始变得复杂,让一些功能“自动起来”是一个好的选择。 在前面的示例中,我们需要在后端为每个前端代码的 URL 指定一个对…

类和对象——(2)类

归纳编程学习的感悟, 记录奋斗路上的点滴, 希望能帮到一样刻苦的你! 如有不足欢迎指正! 共同学习交流! 🌎欢迎各位→点赞 👍 收藏⭐ 留言​📝 只虽然夜晚很长,但天…

选择排序以及改进方案

选择排序以及改进方案 介绍: 选择排序是一种简单直观的排序算法,它的基本思想是在未排序序列中选择最小(或最大)的元素,然后将其放在已排序序列的末尾。选择排序的过程就像是每次从待排序的元素中选择最小的一个&…

C51--4G模块

EC03-DNC:4G通信模块 EC03-DNC 功能特点: 采用最新4G CAT1方案; 支持数据透明传输; 支持TCP、UDP 网络协议; 支持心跳包、注册包功能最大支持64个字节数; 支持MQTT协议,支持接入OneNet平台、百度云平台、阿里云平台的…

计网Lesson4 - 计算机组网模型

文章目录 计算机的连接方式1. 两台计算机的互联2. 多台计算机的互联(旧式)3. 多台计算机的互联 --- 集线器(Hub)4. 网桥5. 多台计算机的互联 --- 交换器(Switch) 计算机的连接方式 1. 两台计算机的互联 网…

ELK日志收集系统-filbeat

filebeat日志收集工具 elk:filebeat日志收集工具和logstash相同 filebeat是一个轻量级的日志收集工具,所使用的系统资源比logstash部署和启动时使用的资源要小的多 filebeat可以运行在非Java环境,它可以代理logstash在非java环境上收集日志…

Boot工程快速启动【Linux】

Boot工程快速启动【Linux】 在idea中打包cd usr/在local文件夹下mkdir app进入app文件夹把打包好的文件(只上传其中的jar)上传到app文件下检查linux中的Java版本,保证和项目的Java 版本保持一致运行 java -jar sp补全***.jar想看效果得查询当…

大模型的开源闭源

文章目录 开源&闭源开源和闭源的优劣势比较开源和闭源对大模型技术发展的影响开源与闭源的商业模式比较国内的大模型开源和闭源的现状和趋势 开源和闭源,两种截然不同的开发模式,对于大模型的发展有着重要影响。 开源让技术共享,吸引了众…

爬虫如何确定HTTP代理IP是否符合自己业务需求?

HTTP代理在许多业务场景中发挥着关键作用,但要确保其能够满足业务需求,需要考虑多个方面的因素。今天我们一起看看,要如何判断HTTP代理是否适合自己的业务,以及在选择HTTP代理时需要考虑的综合因素。 1. 稳定性 稳定性是HTTP代理…

LangChain 14 SequencialChain链接不同的组件

LangChain系列文章 LangChain 实现给动物取名字,LangChain 2模块化prompt template并用streamlit生成网站 实现给动物取名字LangChain 3使用Agent访问Wikipedia和llm-math计算狗的平均年龄LangChain 4用向量数据库Faiss存储,读取YouTube的视频文本搜索I…

计网Lesson3 - 计算机网络评价指标与封包解包

文章目录 计算机网络的性能指标1. 速率2. 带宽3. 吞吐量4. 时延5. 时延带宽积6. 往返时间7. 利用率8. 数据的解包和封包 计算机网络的术语实体![实体](https://img-blog.csdnimg.cn/direct/cbf4ca9ed5ab4df290b5a17b4642c6a1.png)协议服务 计算机网络的性能指标 1. 速率 数据…

MOSFET安全工作区域SOA

Safe Operating Area(SOA)即安全工作区:描述了当MOSFET工作在饱和区时可以处理的最大功率。超出安全工作区,则可能导致元件损坏。 SOA分为五个单独的界限,分别是RDS(on)限制 On Resistance(RDS(on)&#…

算法通关第十三关-青铜挑战数学基础问题

数组元素积的符号 描述 : 已知函数 signFunc(x) 将会根据 x 的正负返回特定值: 如果 x 是正数,返回 1 。如果 x 是负数,返回 -1 。如果 x 是等于 0 ,返回 0 。 给你一个整数数组 nums 。令 product 为数组 nums 中所有元素值的…

大语言模型概述(二):基于亚马逊云科技的研究分析与实践

上期介绍了大语言模型的定义和发展历史,本期将分析基于亚马逊云科技的大语言模型相关研究方向,以及大语言模型的训练和构建优化。 大语言模型研究方向分析 Amazon Titan 2023 年 4 月,亚马逊云科技宣布推出 Amazon Titan 大语言模型。根据…

【SpringCloud系列】@FeignClient微服务轻舞者

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Vue3+java开发组队功能

Vue3java开发系统组队功能 需求分析 创建用户可以创建一个队伍(一个房间队长),设置队伍人数,队伍名称(标题),描述,超时时间。搜索加入,用户可以加入未满的队伍&#xf…

iconfont 使用彩色图标

1、下载iconfont到本地 2、全局安装 iconfont-tools npm install -g iconfont-tools 3、在iconfont解压目录下执行命令、一直回车 iconfont-tools 4、文件拷贝 执行完上述命令后会生成iconfont-weapp目录,将iconfont-weapp目录下的iconfont-weapp- icon.css文件…

ELK日志系统

(一)ELK 1、elk:是一套完整的日志集中处理方案,由三个开源的软件简称组成 2、E:ElasticSearch(ES),是一个开源的,分布式的存储检索引擎(索引型的非关系型数…
最新文章