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.mzph.cn/news/179770.shtml

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

相关文章

C语言——一个数如果恰好等于它的因子之和,这个数就称为“完全数”。

一个数如果恰好等于它的因子之和,这个数就称为“完全数”。例如,6的因子是 1、2、3,而6123。因此6是一个完全数。编程找出 1000 之内的所有完全数。 #include <stdio.h> int main() {int i, j, sum;for (i 1; i < 1000; i) {sum 0; //这一步很重要&#xff0c;每…

Ubuntu:安装Powershell

Powershell的安装与使用&#xff1a; 1&#xff09;安装Powershell&#xff1a;在终端依次运行以下命令即可&#xff1a; $ sudo apt-get update $ sudo apt-get install -y wget apt-transport-https software-properties-common $ wget -q "https://packages.microsof…

【Linux驱动开发】环境搭建Linux驱动开发环境

环境搭建Linux驱动开发环境 1. 简单描述2. 资源3. 安装4. 基本操作和设置 1. 简单描述 基于讯为电子rk3568教程 2. 资源 下载 VMware Workstation Pro 17 链接 Ubuntu 桌面版&#xff08;64位&#xff09; 链接 3. 安装 需要选择自定义硬件&#xff08;内存大于16g 硬盘500g…

java: Internal error in the mapping processor: java.lang.NullPointerException

启动java项目出错&#xff0c;其他人工程没有问题&#xff0c;别着急。 java: Internal error in the mapping processor: java.lang.NullPointerException at org.mapstruct.ap.internal.processor.DefaultVersionInformation.createManifestUrl(DefaultVersionInformation.j…

御云出海记|巴西市场,数字化转型与地区增长的新篇章

在11月的阳光下&#xff0c;巴西圣保罗的热情与活力成为了南半球市场的缩影&#xff0c;尤其是在华为云巴西峰会上。 云峰会亮点 11月22日&#xff0c;圣保罗举办的华为云巴西峰会成为了当地科技界的焦点。此次峰会聚集了数百位政府官员、行业领袖、专家学者&#xff0c;共同讨…

Facebook的这份开源协议使React四面楚歌

如果你觉得一些科技公司看起来很美好&#xff0c;每天都在“改变世界”……你应该看看他们的用户条款和法律文书&#xff0c;藏污纳垢之严重令人震惊。 最近&#xff0c;百度和阿里巴巴内部的软件工程团队不约而同做了一件事——弃用 React。 解释下&#xff1a; React 是一个…

电力智能化系统(智能电力综合监控系统)

电力智能化系统是一个综合性的系统&#xff0c;它利用物联网、云计算、大数据、人工智能等技术&#xff0c;依托电易云-智慧电力物联网&#xff0c;采用智能采集终端和物联网关&#xff0c;将电力设备、用电负荷、电力市场等各个环节有机地联系起来&#xff0c;实现了对电力配送…

【Java】使用 IDEA 快速生成 SpringBoot 模块

项目目录下新建 module 模块 在 pom.xml 更改为 spring initializr 配置之后的 pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchem…

P9240 [蓝桥杯 2023 省 B] 冶炼金属(比值问题)

数学分析&#xff1a; 1. max(最大比值) A/B 余数p&#xff08;p<B&#xff09; > Amax*Bp 反证&#xff1a;若max不为最大,则设maxn为最大比值 (maxn)*Bmax*Bn*Bp1 > A (n*Bp1 > p ,矛盾) 故max为最大比值 2.min(最小比值…

多个nginx共享值、缓存问题

背景 目前我在集成登录认证功能&#xff08;cas&#xff09;&#xff0c;使用的架构是nginxlua&#xff0c;由于我们有多个系统&#xff08;全是前端项目&#xff09;&#xff0c;每套系统都采用nginxlua的方式进行部署&#xff08;即每个系统都是一个nginx&#xff09;&#…

Joint Bilateral Upsampling

Abstract 图像分析和增强任务&#xff08;例如色调映射、着色、立体深度和蒙太奇&#xff09;通常需要在像素网格上计算解决方案&#xff08;例如&#xff0c;曝光、色度、视差、标签&#xff09;。计算和内存成本通常要求在下采样图像上运行较小的解决方案。尽管通用上采样方…

机器学习常用距离度量方法

机器学习常用距离度量方法 前言一、前期准备二、距离度量方法1. 欧氏距离2.曼哈顿距离3.切比雪夫距离4. 闵可夫斯基距离 总结 前言 机器学习中往往通过度量来研究不同样本或数据集之间的差异性&#xff0c;合适的度量方式可以显著提高算法的准确率&#xff0c;因此在接下来的内…

Unity工具脚本-检测资源文件夹是否有预制件是指定层级

效果&#xff1a; 先在菜单栏里面找到Tools/CheckPrefabLayers打开窗口 代码&#xff1a; using System.Collections; using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEngine;public class CheckPrefabLayers : EditorWindow {public in…

【EI会议征稿】第三届航空航天工程与系统国际研讨会(ISAES 2024)

第三届航空航天工程与系统国际研讨会(ISAES 2024) 2024 3rd International Symposium on Aerospace Engineering and Systems 第三届航空航天工程与系统国际研讨会将于2024年3月22-24日在南京召开&#xff01;会议紧密聚焦“航空航天工程”领域的热点和难点问题&#xff0c;…

MT8390(Genio 700)安卓核心板_MTK联发科工业AI主板Linux开发板

MT8390 (Genio 700) 安卓核心板是一款高性能边缘人工智能物联网平台&#xff0c;尺寸仅为45452.2mm。该平台提供高度响应的边缘处理、先进的多媒体功能、各种传感器和连接选项&#xff0c;同时支持多任务操作系统。 Genio 700处理器拥有PS APU性能&#xff0c;高效的芯片内人工…

c++day1

提示并输入一个字符串&#xff0c;统计该字符中大写、小写字母个数、数字个数、空格个数以及其他字符个数 要求使用C风格字符串完成 #include <iostream>using namespace std;int main() {string str;cout << "请输入一个含有大小写字母&#xff0c;空格&am…

java学习part19接口

113-面向对象(高级)-接口的使用_哔哩哔哩_bilibili 1.接口概念 个人认为是一种能力&#xff0c;某个类是否具有某种能力。一个类实现了一个接口就相当于学会了某些功能。 2.使用 接口里的属性都是全局常量public static final&#xff0c;即便不写也会自动加上。 3.多实现 4.接…

Day41 使用listwidget制作简易图片播放器

1.简介 使用QlistWidget实现简易图片播放器&#xff0c;可以打开一个图片序列&#xff0c;通过item的单击事件实现图片的切换&#xff0c;通过设置list的各种属性实现图片预览的显示&#xff0c;美化滚动条即可实现一个简易图片播放器。 2.效果 3.实现步骤&#xff1a; 1.初始…

【沐风老师】3DMAX拼图建模工具MaxPuzzle2D插件使用方法详解

MaxPuzzle2D拼图建模工具使用帮助 MaxPuzzle2D拼图建模工具&#xff0c;拼图建模“彩虹系列”插件&#xff0c;是一款用MAXScript脚本语言开发的3dMax拼图建模小工具&#xff0c;可以创建2D或3D的拼图图形阵列。这让需要拼图建模的设计师大大节省了时间。 MaxPuzzle2D工具界面&…

REST-Assured--JAVA REST服务自动化测试的Swiss Army Knife

什么是REST-Assured REST Assured是一套基于 Java 语言实现的开源 REST API 测试框架 Testing and validation of REST services in Java is harder than in dynamic languages such as Ruby and Groovy. REST Assured brings the simplicity of using these languages into t…