一文彻底搞懂Redis底层数据结构

文章目录

  • 1. 数据结构与数据类型的关系
  • 2. 底层数据结构详解
    • 2.1 SDS: 简单动态字符串
    • 2.2 双端链表
    • 2.3 压缩列表
    • 2.4 哈希表
    • 2.5 整数集合
    • 2.6 跳表
    • 2.7 quicklist
    • 2.8 listpack

1. 数据结构与数据类型的关系

Redis是一个基于内存的数据存储系统,它支持多种数据结构和数据类型,每种数据结构和数据类型都有其特定的用途和适用场景。下面是Redis支持的主要数据结构及其对应的数据类型:

  • 字符串(String):字符串是Redis中最简单的数据结构,可以存储文本、数字等任意类型的数据。在Redis中,字符串类型被用于缓存、计数器等场景。
  • 列表(List):列表是一个有序的字符串集合,可以包含重复的元素。在Redis中,列表适用于存储按顺序排列的数据,比如消息队列、任务列表等。
  • 哈希表(Hash):哈希表是一个键值对集合,每个键值对都存储在一个哈希表中。在Redis中,哈希表适用于存储对象的属性和值之间的映射关系,比如存储用户信息、配置信息等。
  • 集合(Set):集合是一个无序的字符串集合,不允许重复元素。在Redis中,集合适用于存储唯一的、不重复的数据,比如用户标签、文章标签等。
  • 有序集合(Sorted Set):有序集合是一个有序的字符串集合,每个字符串都关联一个分数(score)。在Redis中,有序集合适用于存储按分数排序的数据,比如排行榜、计分系统等。
    在这里插入图片描述

2. 底层数据结构详解

2.1 SDS: 简单动态字符串

SDS(Simple Dynamic Strings)是Redis中用于表示字符串的数据结构之一,它具有以下特点:

  • 灵活性: SDS 可以存储字符串,也可以存储二进制数据,包括空字符,因此在处理二进制数据时更为灵活,不受空字符的限制。
  • 缓存长度信息: SDS 在头部保存了字符串的长度信息,因此可以在 O(1) 的时间复杂度内获取字符串的长度,而不需要遍历整个字符串,提高了获取长度的效率。
  • 动态扩容: SDS 可以根据实际存储的数据动态扩容,当字符串长度变长时,SDS 会自动进行内存的扩展,而不需要手动管理内存,提高了内存管理的便利性。

SDS 的设计使得它在处理字符串时更为灵活和高效,因此在 Redis 中被广泛应用于存储和处理字符串数据。

2.2 双端链表

Redis中的 List 就是⽤双端链表实现的,双端链表(Doubly Linked List)是一种链表数据结构,每个节点除了包含指向下一个节点的指针外,还包含指向上一个节点的指针,双端链表的链表节点可以保存不同类型的值,⽀持在两端进⾏元素的快速插⼊和删除,并且链表结构提供了表头指针和表尾指针,获取链表的表头节点和表尾节点的时间复杂度只需O(1);
获取链表数量的时间复杂度也只需O(1)。

双端链表的节点结构通常包含以下两个指针:

  • 指向下一个节点的指针(Next Pointer):指向链表中的下一个节点。
  • 指向上一个节点的指针(Previous Pointer):指向链表中的上一个节点。

双端链表的优点:

  • 可以在头部和尾部高效地进行插入和删除操作,时间复杂度为 O(1)。
  • 可以支持双向遍历,能够从头部和尾部同时进行遍历操作。

双端链表的缺陷:

  • 链表每个节点之间的内存都是不连续的,意味着⽆法很好利⽤ CPU 缓存
  • 保存⼀个链表节点的值都需要⼀个链表节点结构头的分配,内存开销较⼤。

双端链表常被用于需要频繁进行插入和删除操作,并且需要支持双向遍历的场景,比如实现队列、栈、LRU缓存等数据结构和算法。

2.3 压缩列表

压缩列表(ZipList)是一种用于在 Redis 中紧凑存储列表和哈希表数据的数据结构。它是由一系列特定编码格式的连续内存块组成的顺序型数据结构,每个内存块称为一个节点(entry)。每个节点可以存储一个字节数组或整数值,并且可以根据实际存储的数据动态地调整节点的长度。

压缩列表的主要特点包括:

  • 紧凑存储:压缩列表采用紧凑的内存布局,节点之间紧密相连,节省了内存空间。
  • 可变长度:每个节点的长度可以根据实际存储的数据动态地调整,避免了不必要的内存浪费。
  • 支持多种数据类型:压缩列表可以存储不同类型的数据,包括字符串和整数值。
  • 快速随机访问:压缩列表支持通过索引快速定位到指定位置的节点,因此可以在 O(1) 的时间复杂度内实现随机访问。
  • 适应于小规模数据:压缩列表适用于存储小规模的数据集,当数据量较大时,会转换为其他更适合大规模数据的数据结构,比如双端链表或跳表。

压缩列表在 Redis 中被广泛应用于列表和哈希表数据类型的实现中,能够高效地存储和操作数据,提升了 Redis 的性能和内存利用率。

2.4 哈希表

哈希表(Hash Table)是一种用于存储键值对(key-value pairs)的数据结构,在 Redis 中被广泛应用于实现各种数据类型,如哈希表(Hashes)和集合(Sets)等。

在哈希表中,每个键都经过哈希函数处理后映射到一个唯一的索引位置,然后将对应的值存储在该位置上。这样,通过键可以快速定位到对应的值,实现了高效的查找操作。

哈希表的主要特点包括:

  • 快速查找:通过键进行哈希计算,可以快速定位到对应的值,具有 O(1) 的平均时间复杂度。
  • 灵活性:哈希表可以存储各种类型的键值对,不限于字符串和整数。
  • 动态扩容:在数据量增加时,哈希表可以动态地扩容以适应新的键值对的存储需求。
  • 碰撞处理:由于哈希函数可能会将不同的键映射到同一个索引位置上,因此需要使用碰撞处理技术来解决冲突,常见的方法包括链地址法和开放定址法等。

在 Redis 中,哈希表被用于实现哈希表数据类型(Hashes),它可以存储多个键值对,并且支持对单个键值对的增、删、改、查等操作。此外,哈希表还被用于实现集合数据类型(Sets)中的有序集合(Sorted Sets),用于存储成员和对应的分值之间的关系。

2.5 整数集合

整数集合(Integers Set)是 Redis 中的一种特殊数据结构,用于高效地存储整数值的集合。它是为了在存储一组整数时,提供更加紧凑和高效的存储方式而设计的。

整数集合的主要特点包括:

  • 紧凑存储:整数集合使用紧凑的数据结构存储整数值,不像普通的数组那样每个元素都需要占用固定的内存空间,而是根据整数的大小动态调整所需的存储空间,节省了内存的使用。
  • 快速查找:由于整数集合中的元素是有序的,并且使用了特定的算法进行存储和查找,因此可以在 O(logN) 的时间复杂度内实现查找操作,其中 N 表示整数集合中的元素个数。
  • 支持多种整数类型:整数集合可以存储多种整数类型,包括 int16、int32、int64 等,根据存储的整数值的大小自动选择合适的数据类型。
  • 动态调整:整数集合在存储整数值的过程中,会根据需要动态调整存储空间,避免了固定大小数组可能带来的空间浪费或溢出问题。

整数集合在 Redis 中被广泛应用于存储集合数据类型(Sets)中的整数成员,例如用于存储用户 ID、商品 ID 等。由于其高效的存储方式和快速的查找性能,使得整数集合成为了处理整数集合类数据的首选数据结构之一。

2.6 跳表

跳跃表是⼀种在链表基础上改进过来的,实现了⼀种「多层」的有序链表,当数据量很⼤时,跳表的查找复杂度就
是O(logN)。在 Redis 中,有序集合(Sorted Set)就是通过跳表来实现的,因为跳表具有快速的查找和插入操作,非常适合用于实现有序集合类数据结构。

跳表的查找过程?

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

2.如果当前节点的权重⼩于要查找的权重时,跳表就会访问该层上的下⼀个节点。

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

4.如果上⾯两个条件都不满⾜,或者下⼀个节点为空时,跳表就会使⽤⽬前遍历到的节点的 level 数组⾥的下⼀层指
针,然后沿着下⼀层指针继续查找。

跳表的主要特点包括:

  • 多级索引:跳表通过维护多级索引,使得在查找时可以跳过部分元素,从而减少查找的时间复杂度。每一级索引都是一个- 有序链表,最底层的链表包含所有元素,而上层的链表包含更少的元素,相邻两级索引的元素数量相差较大。
  • 插入和删除高效:由于跳表中的每一级索引都是有序的链表,因此在插入和删除元素时,只需要调整相邻节点的指针即可,不需要像平衡树那样进行复杂的平衡操作,因此插入和删除操作的时间复杂度为 O(logN),其中 N 表示跳表中的元素数量。
  • 支持快速查找:由于跳表维护了多级索引,因此在查找时可以根据索引快速定位到目标元素所在的范围,然后再在范围内使用顺序查找进行查找,这样可以将查找的时间复杂度降低到 O(logN)。

跳表相对于平衡树来说实现更加简单,并且在实际应用中具有较好的性能表现。

2.7 quicklist

Quicklist(快速列表)是 Redis 中用于存储列表类型数据的一种高效数据结构。它是双向链表 + 压缩列表的混合体,quicklist 就是⼀个链表,⽽链表中的每个元素⼜是⼀个压缩列表。 quicklist 解决办法,通过控制每个链表节点中的压缩列表的⼤⼩或者元素个数,来规避连锁更新的问题。因为压缩列表元素越少或越⼩,连锁更新带来的影响就越⼩,从⽽提供了更好的访问性能。可以在列表的两端进行快速插入和删除操作,并且在内部使用压缩列表来节省内存空间。

快速列表的主要特点包括:

  • 双向链表特性:快速列表包含多个节点,每个节点都是一个双向链表。这使得在列表的两端进行插入和删除操作时具有较高的效率,时间复杂度为 O(1)。
  • 压缩列表优势:每个节点内部使用压缩列表来存储列表元素。压缩列表是一种紧凑的、可变长度的连续内存块,可以高效地存储多个元素,并且在元素数量较小时节省内存空间。
  • 节点间指针:快速列表中的节点之间通过指针进行连接,使得可以在节点之间进行快速的遍历和操作。
  • 灵活性:快速列表可以根据实际存储的数据动态调整节点的数量和大小,从而实现空间利用的最大化和性能的最优化。

由于快速列表同时具备双向链表和压缩列表的优势,因此在 Redis 中被广泛应用于存储列表类型数据,如列表、队列等,以满足不同场景下的需求。

2.8 listpack

Listpack 是 Redis 中用于存储列表类型数据的一种紧凑、高效的数据结构。它是一种类似于压缩列表的数据结构,但相比于压缩列表,Listpack 在一些方面进行了优化和改进。listpack 没有压缩列表中记录前⼀个节点⻓度的字段,listpack 只记录当前节点的⻓度,当我们向 listpack 加⼊⼀个新元素的时候,不会影响其他节点的⻓度字段的变化,从⽽避免了压缩列表的连锁更新问题。

Listpack 的主要特点包括:

  • 紧凑性:Listpack 在内存中存储数据时非常紧凑,它只记录当前节点的长度,而不记录前一个节点的长度。这种设计避免了像压缩列表那样可能引发的连锁更新问题,提高了内存使用的效率。
  • 高效性:Listpack 在插入和删除操作时具有较高的性能,因为它不需要更新前一个节点的长度字段。这使得对于列表中的某个节点进行操作时,不会影响到其他节点的数据结构,减少了操作的开销和复杂度。
  • 灵活性:Listpack 可以根据实际存储的数据动态调整节点的大小和数量,从而在不同场景下实现空间的最大化利用和性能的最优化。

总的来说,Listpack 是 Redis 中用于存储列表类型数据的一种高效、灵活的数据结构,它在内存使用效率和操作性能上具有较好的表现,适用于存储大量的列表数据,并且在 Redis 内部的实现中得到了广泛应用。

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

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

相关文章

vue项目报这个错是 Same `value` exist in the tree: 0008E3000E1A?

警告 "Same value exist in the tree: 0008E3000E1A" 表示在树形选择器中存在相同的值。这通常是由于树形选择器的数据中存在重复的值造成的。就是返回的值中,有俩个id相同

基于K-近邻的PLOSAR图像分类

🎀个人主页: https://zhangxiaoshu.blog.csdn.net 📢欢迎大家:关注🔍点赞👍评论📝收藏⭐️,如有错误敬请指正! 💕未来很长,值得我们全力奔赴更美好的生活&…

mybatis实践篇(二)

自定义类型处理器(TypeHandler) 实体 package com.wyl.mybatis.entity;import java.util.Date;/*** Description 省市区-字典* Author wuyilong* Date 2024-02-26*/public class FullCity {private static final long serialVersionUID 1L;/*** 主键I…

第十三届蓝桥杯省赛真题 Java A 组【原卷】

文章目录 发现宝藏【考生须知】试题 A: 裁纸刀试题 B: 寻找整数试题 C : \mathrm{C}: C: 求和试题 D: GCD试题 E: 蜂巢试题 F : \mathrm{F}: F: 全排列的价值试题 G: 青蛙过河试题 H \mathrm{H} H : 因数平方和试题 I: 最优清零方案试题 J : \mathrm{J}: J: 推导部分和 发现…

Unity Mesh简化为Cube mesh

Mesh简化为Cube mesh 🍳食用🥙子物体独立生成CubeMesh🥪合并成一个CubeMesh🌭Demo 🍳食用 下载并导入插件👈即可在代码中调用。 🥙子物体独立生成CubeMesh gameObject.ToCubeMesh_Invidual()…

Win11文件右键菜单栏完整显示教程

近日公司电脑升级了win11,发现了一个小麻烦事,如下图: 当我想使用svn或git的时候必须要多点一下,这忍不了,无形之中加大了工作量! 于是,菜单全显示教程如下: 第一步:管…

C#宿舍信息管理系统

简介 功能 1.发布公告 2.地理信息与天气信息的弹窗 3.学生信息的增删改查 4.宿舍信息的增删改查 5.管理员信息的增删改查 6.学生对宿舍物品的报修与核实 7.学生提交请假与销假 8.管理员对保修的审批 9.管理员对请假的审批 技术 1.采用C#\Winform开发的C\S系统 2.采用MD5对数据…

Centos7安装Python3.8

1.安装编译相关工具 yum -y groupinstall "Development tools" yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel yum install libffi-devel -y2.下载安装包…

GPT模型部署后续:聊天机器人系统的扩展与优化

一、多轮对话支持 为了实现多轮对话支持,我们需要维护用户的会话上下文。这可以通过在服务器端使用一个字典来存储会话状态实现。 目录 一、多轮对话支持 下面是一个简单的扩展例子: 二、性能优化 三、用户界面与交互优化 下面是一个简单的HTML示例&…

一文搞懂 YOLOv9 训练推理全流程 | YOLOv9你绝对不知道的细节!

文章地址:https://arxiv.org/pdf/2402.13616.pdf 代码地址:https://github.com/WongKinYiu/yolov9 前言 在这篇博客中,我们来聊聊 YOLOv9。首先,值得注意的一点是,YOLOv9的变化相对较小,它仍然基于YOLOv5的…

微信小程序button动态跳转到页面

微信小程序中如何动态的跳转到某个页面。 目录 1、首先在js文件中定义事件函数 2、在页面中进行传参调用 3、其它跳转方法简单说明 1、首先在js文件中定义事件函数 goto(e){const urle.currentTarget.dataset.url;wx.navigateTo({url: url})}, 2、在页面中进行传参调用 &l…

【随笔】Git -- 常用命令(四)

💌 所属专栏:【Git】 😀 作  者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! 💖 欢迎大…

带你学会深度学习之循环神经网络[RNN] - 2

前言 笔者写下此系列文章是希望在复习人工智能相关知识同时为想学此技术的人提供一定帮助。 图源网络,所有者可随时联系笔者删除。 代码不代表全部实现,只是为展示模型的关键结构。 与CNN不同,RNN被设计用来处理序列数据。它通过在网络的…

3GPP 协议资料学习和文档下载

一、登录3GPP官网 3GPP – The Mobile Broadband Standard 二、选择Specifications Per TSG Round 三、选择ftp下载路径 四、选择不同阶段的3GPP协议 包含了从1999年到R18,甚至更新到当前最新的协议。 五、查看对应版本的LTE或者5G NR协议 其中LTE射频相关章节为36.521系列&…

小目标检测篇 | YOLOv8改进之增加小目标检测层(针对Neck网络为AFPN)

前言:Hello大家好,我是小哥谈。小目标检测是计算机视觉领域中的一个研究方向,旨在从图像或视频中准确地检测和定位尺寸较小的目标物体。相比于常规目标检测任务,小目标检测更具挑战性,因为小目标通常具有低分辨率、低对比度和模糊等特点,容易被背景干扰或遮挡。本篇文章就…

MP4如何把视频转MOV格式? MP4视频转MOV格式的技巧

在现代的数字媒体时代,视频格式转换成为了许多用户必须掌握的技能。特别是将MP4视频转换为MOV格式,这对于需要在Apple设备上播放或编辑视频的用户来说尤为重要。本文将详细介绍如何将MP4视频转换为MOV格式,帮助读者轻松应对不同设备和平台的需…

三端可调正稳压器集成电路D317——输出电压范围是1.2V至37V,负载电流最大为1.5A

D317大电流可调稳压电路 1、 概述: D317是一款三端可调正稳压器集成电路,其输出电压范围是1.2V至37V,负载电流最大为1.5A。它的使用非常简单,仅需两个外接电阻来设置输出电压。此外,它的电压线性度和负载调整率也比标准…

使用Python制作一个批量查询搜索排名的SEO免费工具

搭建背景 最近工作中需要用上 Google SEO(搜索引擎优化),有了解过的朋友们应该都知道SEO必不可少的工作之一就是查询关键词的搜索排名。关键词少的时候可以一个一个去查没什么问题,但是到了后期,一个网站都有几百上千…

浏览器工作原理与实践--渲染流程(上):HTML、CSS和JavaScript,是如何变成页面的

在上一篇文章中我们介绍了导航相关的流程,那导航被提交后又会怎么样呢?就进入了渲染阶段。这个阶段很重要,了解其相关流程能让你“看透”页面是如何工作的,有了这些知识,你可以解决一系列相关的问题,比如能…

获取第三方小程序指定页面的path

获取第三方小程序指定页面的path wx.navigateToMiniProgramappIdpathwx.navigateToMiniProgram 在开发小程序时需要跳转到第三方小程序指定页面时,需通过wx.navigateToMiniProgram方法完成。其中有两个主要参数appId和path,文本以问卷星为例,分享两者获取方法。 appId 在…