【面试八股总结】Redis数据结构及底层实现

一、五种基本数据结构

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

结构类型结构可存储值结构读写能力使用命令底层数据结构
String字符串、整数或浮点数对字符串或字符串的一部分进行操作,对整数或浮点数进行自增或自减get、set、delSDS
List链表,链表上每个节点包含一个字符串对链表两端进行push和pop操作,读取单个或多个元素;根据值查找或删除元素lpush、lrange、index、lpop双向链表/压缩列表
Set字符串的无序集合是否存在、添加、获取、删除字符串;计算交集、并集、差集等sadd、smember、sismember、srem哈希表/整数集合
Hash包含键值对的无序散列表添加、获取、删除单个元素hset、hget、hgetall、hdel压缩列表/哈希表
Zset和Hash一样存储键值对字符串成员与浮点分数之间的有序映射、元素的排列顺序由分数的大小决定;包含方法由添加、获取、删除单个元素及根据分值范围或成员获取元素zadd、zrange、zrangebyscore、zrem压缩列表/跳表

Redis 五种数据类型的应用场景:

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

二、四种新增数据结构

BitMap(2.2 版新增)

        bit 是计算机中最小的单位,使用它进行储存将非常节省空间,特别适合⼀些数据量大且使用二值统计的场景,比如签到、判断用户登陆状态、连续签到用户总数等;

HyperLogLog(2.8 版新增)

        HyperLogLog用于基数统计,统计规则是基于概率完成的,不准确,标准误算率是 0.81%。优点是,在输入元素的数量或者体积非常大时,所需的内存空间总是固定的、并且很小。可用于海量数据基数统计的场景,比如百万级网页 UV 计数等;

GEO(3.2 版新增)

        存储地理位置信息的场景,并对存储的信息进⾏操作。底层是由Zset实现的,使用GeoHash编码方法实现了经纬度到Zset中元素权重分数的转换,这其中的两个关键机制就是「对⼆维地图做区间划分」和「对区间进⾏编码」。 ⼀组经纬度落在某个区间后,就⽤区间的编码值来表示,并把编码值作为Zset元素的权重分数比如滴滴叫车;

Stream(5.0 版新增)

        消息队列,相比于基于 List 类型实现的消息队列,有这两个特有的特性:自动生成全局唯一消息ID,支持以消费组形式消费数据。

三、底层数据结构实现

1. 简单动态字符串(Simple Dynamic String,SDS)

  • SDS可以存储字符串,还可以存储二进制数据,包括空字符。这使得SDS在处理二进制数据时更为灵活,不受空字符的限制。
  • 缓存长度信息:SDS在头部保存了字符串的长度信息,因此可以在0(1)的时间复杂度内获取字符串的长度。这样,不需要遍历整个字符串来计算长度,提高了获取长度的效率。
  • 动态扩容:SDS可以根据实际存储的数据动态扩容。当字符串长度变长时,SDS会自动进行内存的扩展,而不需要像C语言中的传统字符串那样手动管理内存。

2. 双向链表

        双端链表的链表节点可以保存不同类型的值,支持在两端进行元素的快速插入和删除,并且链表结构提供了表头指针和表尾指针,获取链表的表头节点和表尾节点的时间复杂度只需O(1);获取链表数量的时间复杂度也只需O(1);

缺点:

  • 链表每个节点之间的内存都是不连续的,意味着无法很好利用 CPU 缓存;
  • 保存一个链表节点的值都需要一个链表节点结构头的分配,内存开销较大

3. 压缩列表

        压缩列表是一种紧凑的、可变长度,由连续内存块组成的顺序型数据结构,类似于数组,被用于存储列表和哈希表的数据。压缩列表在内存使用效率上相对较高,它可以根据数据大小进行灵活的扩容和收缩。

缺点:

  • 空间扩展操作也就是重新分配内存,因此连锁更新一旦发生,就会导致压缩列表占用的内存空间要多次重新分配,直接影响到压缩列表的访问性能。
  • 如果保存的元素数量增加了,或是元素变大了,会导致内存重新分配,会有连锁更新的问题。
  • 压缩列表只会用于保存的节点数量不多的场景,只要节点数量足够小,即使发生连锁更新也能接受。

4. 哈希表

        哈希表是一种保存键值对(key-value)的数据结构。优点在于能以O(1)的复杂度快速查询数据。Redis 采用了拉链法来解决哈希冲突,在不扩容哈希表的前提下,将具有相同哈希值的数据串起来,形成链接。

5. 整数集合

        整数集合是一种专门用于存储整数值的数据结构,通过紧凑的二进制表示,提高了整数存储的效率。

6. 跳表

        跳跃表是一种在链表基础上改进过来的,实现了一种多层的有序链表,当数据量很大时,跳表的查找复杂度就是O(logN)。用于实现有序集合(Sortedset)。

跳表的查找过程?

        查找一个跳表节点的过程时,跳表会从头节点的最高层开始,逐一遍历每一层。在遍历某一层的跳表节点时,会用跳表节点中的 SDS 类型的元素和元素的权重来进行判断:

  • 如果当前节点的权重小于要查找的权重时,跳表就会访问该层上的下一个节点。
  • 如果当前节点的权重等于要查找的权重时,并且当前节点的 SDS 类型数据小于要查找的数据时,跳表就会访问该层上的下一个节点。

        如果上面两个条件都不满足,或者下一个节点为空时,跳表就会使用目前遍历到的节点的level 数组里的下一层指针,然后沿着下一层指针继续查找。

举个🌰:

        从头节点的顶层开始,查到第一个大于指定元素的节点时,退回上一节点,在下一层继续查找。比如我们要查找16:

  • 从头节点的最顶层开始,先到节点7。
  • 7的下一个节点是39,大于16,因此我们退回到7
  • 从7开始,在下一层继续查找,就可以找到16。

        为了避免插入操作的时间复杂度是O(N),跳表每层的数量不会严格按照2:1的比例,而是对每个要插入的元素随机一个层数。随机层数的计算过程如下:每个节点都有第一层,那么它有第二层的概率是p,有第三层的概率是p*p,不能超过最大的层数。

 7. quicklist

        quicklist 就是双向链表+压缩列表组合,quicklist 就是一个链表,而链表中的每个元素又是一个压缩列表。quicklist 通过控制每个链表节点中的压缩列表的大小或者元素个数,来规避连锁更新的问题。因为压缩列表元素越少或越小,连锁更新带来的影响就越小,从而提供了更好的访问性能。

8. listpack

        listpack 没有压缩列表中记录前一个节点长度的字段,listpack 只记录当前节点的长度,当我们向 listpack加入一个新元素的时候,不会影响其他节点的长度字段的变化,从而避免了压缩列表的连锁更新问题。

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

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

相关文章

【Java】已解决java.util.EmptyStackException异常

文章目录 一、问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决java.util.EmptyStackException异常 一、问题背景 java.util.EmptyStackException是Java在使用java.util.Stack类时可能会遇到的一个异常。这个异常通常在尝试从空的栈中弹出&am…

[吃瓜教程]概览西瓜书+南瓜书第1、2章

第一章 绪论 1.1机器学习的定义,什么是机器学习? 1)机器学习是这样一门学科,它致力于研究如何通过计算的手段,利用经验来改善系统自身的性能。 2)机器学习所研究的主要内容是关于在计算机上从数据中产生模型的算法&a…

【golang学习之旅】Go程序快速开始 Go程序开发的基本注意事项

系列文章 【golang学习之旅】使用VScode安装配置Go开发环境 【golang学习之旅】报错:a declared but not used 【golang学习之旅】Go 的基本数据类型 【golang学习之旅】深入理解字符串string数据类型 【golang学习之旅】go mod tidy 【golang学习之旅】记录一次 p…

linux配置Vnc Server给Windows连接

1. linux 安装必要vnc server和桌面组件 sudo apt -y install tightvncserversudo apt install xfce4 xfce4-goodies2. linux 配置vncserver密码 #bash vncserver参考: https://cn.linux-console.net/?p21846#google_vignette 3. 将启动桌面命令写入.vnc/xstartup # .vnc/x…

了解指标体系1:指标是大数据开发中的关键要素

在大数据开发的过程中,指标体系是一个至关重要的概念。本文将介绍什么是指标,为什么它们如此重要,以及如何在大数据项目中有效地构建和应用指标体系。 目录 什么是指标?指标的类型为什么指标如此重要?如何构建有效的指…

2024最新自动化测试 —— Jest 测试框架应用

什么是自动化测试 在软件测试中,自动化测试指的是使用独立于待测软件的其他软件来自动执行测试、比较实际结果与预期并生成测试报告这一过程。在测试流程已经确定后,测试自动化可以自动执行的一些重复但必要的测试工作。也可以完成手动测试几乎不可能完…

xcode和iPhone真机或者watch真机连接问题

1.如果真机是第一次连接xocde,就需要开启真机上的开发者模式,开启开发者模式的方式: iphone/ipad开启方式: 设置 > 隐私与安全 > 开发者模式 > 开启,然后重启就可以了 watch设置:很麻烦,看文章…

对身外之物,不必在意

不管对待自己还是他人,外在的条件不值得挂怀,人在不得已颠沛流离时期,吃不好、穿不好,都应该从容接受。

外汇天眼:盈透证券为客户提供更丰富的欧洲衍生品交易渠道

电子交易巨头盈透证券(纳斯达克代码:IBKR)今日宣布,通过Cboe欧洲期权交易所(CEDX)新增欧洲股票期权和欧洲指数期货及期权。这一新增功能使得盈透证券的客户可以在单一统一平台上,除了股票、期权…

力扣469A

文章目录 1. 题目链接2. 题目代码3. 题目总结4. 代码分析 1. 题目链接 I Wanna Be the Guy 2. 题目代码 #include<iostream> #include<set> using namespace std; int main(){int highestLevelOfGame;cin >> highestLevelOfGame;set<int> levelCanPas…

【profinet】从站开发要点

目录 0、常见缩写及关键字注释 1、profinet简介 2、profinet协议栈 3、profinet数据帧 4、profinet网络解决方案示例 5、Application areas 注&#xff1a;本文主要简述profinet从站开发涉及到的知识点。【不足之处后续慢慢补充】。 0、常见缩写及关键字注释 MRP: Media…

移动硬盘接入mac无法复制文件进去怎么办,mac里的文件如何存进移动硬盘

如果要传输的文件数据量比较大&#xff0c;相比于使用U盘&#xff0c;移动硬盘是更多的选择。移动硬盘可存储量大、传输速度快&#xff0c;是实用性比较强的储存设备。不仅是Windows设备&#xff0c;Mac电脑也经常使用到移动硬盘。但有时候&#xff0c;移动硬盘在Mac上不能传文…

XHS-Downloader是一款小红书图片视频下载工具

这款软件可以提取账号发布、收藏、点赞作品链接&#xff1b;提取搜索结果作品链接、用户链接&#xff1b;下载小红书作品信息&#xff1b;提取小红书作品下载地址&#xff1b;下载小红书无水印作品文件&#xff01; &#x1f4d1; 功能清单 ✅ 采集小红书图文 / 视频作品信息…

【Pmac】PMAC QT联合开发中各种可能遇到的坑

目录 1. 错误 C2027 使用了未定义类型“PCOMMSERVERLib::DEVUPLOAD”2. 输入了正确的pmac的ip地址&#xff0c;没有显示可选的pmac设备3. Pmac DTC-28B无读数 使用QT编写PMAC上位机程序时&#xff0c;利用QT中的dump工具可以将pcommserver.exe转化为pcommserverlib.h和pcommser…

AMBA-CHI协议详解(四)

《AMBA 5 CHI Architecture Specification》 AMBA-CHI协议详解&#xff08;一&#xff09; AMBA-CHI协议详解&#xff08;二&#xff09; AMBA-CHI协议详解&#xff08;三&#xff09; AMBA-CHI协议详解&#xff08;四&#xff09; 文章目录 2.3.3 Atomic transactions2.3.4 S…

Hadoop3:MapReduce中的Shuffle机制

一、流程图 Shuffle是Map方法之后&#xff0c;Reduce方法之前的数据处理过程称。 二、图解说明 1、数据流向 map方法中context.write(outK, outV);开始&#xff0c;写入环形缓冲区&#xff0c;再进行分区排序&#xff0c;写到磁盘 reduce方法拉取磁盘上的数据&#xff0c;…

swift使用swift-protobuf协议通讯,使用指北

什么是Protobuf Protobuf&#xff08;Protocol Buffers&#xff09;协议&#x1f609; Protobuf 是一种由 Google 开发的二进制序列化格式和相关的技术&#xff0c;它用于高效地序列化和反序列化结构化数据&#xff0c;通常用于网络通信、数据存储等场景。 为什么要使用Proto…

【QT5】<重点> QT多线程

文章目录 前言 一、QThread创建多线程 二、QMutex基于互斥量的同步 三、QReadWriteLock线程同步 四、QWaitCondition线程同步 五、QSemaphore基于信号量的同步 前言 本篇记录学习QT多线程的知识&#xff0c;参考视频13.1QThread创建多线程程序_哔哩哔哩。若涉及版权问题…

Linux - 进程

一、什么是进程 首先&#xff0c;Linux是一个多用户多进程的操作系统&#xff0c;系统上可以同时运行多个进程。 进程的产生&#xff1a;①是在执行程序或者命令时产生的&#xff1b;②定时任务进程 进程的类型&#xff1a;前台进程/后台进程 前台进程&#xff1a;一个终端…

迭代器模式观察者模式

文章目录 1.引出迭代器模式1.展示院系结构2.传统方式 2.迭代器模式解决院系结构展示问题1.基本介绍2.原理类图3.类图4.代码实现1.Department.java 存储信息的对象2.College.java 被迭代的类型接口3.ComputerCollege.java 被迭代的具体实现类&#xff0c;存储数据并将其在创建迭…