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

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

时间:2024-06-18 16:58:26浏览次数:28  
标签:八股 元素 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 数组里的下一层指针,然后沿着下一层指针继续查找。

举个

标签:八股,元素,Redis,列表,链表,跳表,字符串,数据结构,节点
From: https://blog.csdn.net/rabbit_qi/article/details/138095617

相关文章

  • 采用java语言+Redis+RabbitMQ开发的 门诊his系统源码 一站式的门诊his系统 门诊业务流
    采用java语言+Redis+RabbitMQ开发的门诊his系统源码一站式的门诊his系统门诊业务流程医院信息系统(HIS系统)门诊业务是医院信息化建设的重要组成部分之一,它涵盖了医院门诊部门涉及的各项业务。HIS系统门诊业务的实施,可以实现医院门诊业务的信息化管理和数据化处理,提高医疗服......
  • 探索Redis的运行情况和数据——一次有趣的Redis旅程【GPT生成】
    探索Redis的运行情况和数据——一次有趣的Redis旅程前言Redis,一个高性能的键值对数据库,广泛应用于缓存、会话管理和实时数据处理。如果你正在使用Redis,你可能会好奇如何检查它的运行情况,以及它究竟存储了哪些数据。在这篇博客中,我将带你一起使用Xshell连接到服务器,探索Redis的奥......
  • 【408考点之数据结构】数据结构的基本概念
    数据结构的基本概念基本概念和术语数据结构是计算机科学中一个非常重要的概念,它描述了数据元素之间的关系及其在计算机内存中的组织方式。理解数据结构的基本概念和术语是学习数据结构的第一步。数据结构可以分为逻辑结构和存储结构两类。逻辑结构是指数据元素之间的逻辑......
  • 【408考点之数据结构】算法和算法评价(时间空间复杂度)
    算法和算法评价算法的基本概念在计算机科学中,算法是解决特定问题的一系列步骤。一个好的算法应该具备以下五个基本特性:有穷性:算法必须在有限的步骤内终止。确定性:每一步骤都必须明确,没有歧义。可行性:算法的每个步骤都可以通过基本运算在有限时间内完成。输入:一个算法有零......
  • Redis常见数据类型及其常用命令详解
    文章目录一、Redis概述二、Redis常用命令1.通用命令1.1KEYS:查看符合模板的所有key1.2DEL:删除一个指定的key1.3EXISTS:判断key是否存在1.4EXPIRE:给一个key设置有效期,有效期到期时该key会被自动删除1.5TTL:查看一个key的剩余有效期1.6COPY:复制Redis数据库......
  • 从零开始学数据结构系列之第三章《先序线索二叉树查找及总代码》
    文章目录查找下一个节点总代码往期回顾查找下一个节点​  我们为啥没有像中序二叉树一样有第一个节点,因为我们一开始最大就是我们的根节点,所以无需遍历去寻找我们的第一个节点,我们的T就是我们的第一个节点​我们回过来看中序线索二叉树的节点应该是怎么写的/*......
  • 矿大数据结构 实验二
     目录 A:子串个数B.模式串C.主对角线上的数据和D.顺时针排螺旋阵E:汉诺塔游戏中的移动F.树的先根遍历G.树的后根遍历A:子串个数本题未考虑重复的情况,直接使用公式既可考虑重复的情况:不同子串个数-洛谷#include<bits/stdc++.h>usingnamespacestd;i......
  • C语言数据结构队列实现-链表队列
    简单实现了下链表队列代码如下#include<stdio.h>#include<stdlib.h>typedefstructNode{intdata;structNode*next;}Node;//入队列voidinsertList(Node*head,intelem){Node*temp=head;Node*newNode=(Node*)malloc(sizeof(Node));......
  • [C++][数据结构][红黑树]详细讲解
    目录1.红黑树的概念2.红黑树的性质3.红黑树节点的定义4.红黑树的结构5.红黑树的插入操作1.cur为红,p为红,g为黑,u存在且为红2.cur为红,p为红,g为黑,u不存在/u存在且为黑--单旋+变色3.cur为红,p为红,g为黑,u不存在/u存在且为黑--双旋+变色6.红黑树的迭代器1.begin()与end()2.o......
  • 数据结构代码常用模板
    目录线性表顺序表单链表循环单链表栈和队列顺序栈链栈队列树与二叉树二叉树的遍历并查集哈夫曼树串KMP图深度优先搜索与广度优先搜索拓扑排序克洛斯卡尔最小生成树弗洛伊德最短路排序快速排序直接插入排序希尔排序简单选择排序冒泡排序线性表顺序表#include<iostream>#includ......