Redis数据结构

Redis六种存储结构详解 文章目录一、简单动态字符串SDS1.1 SDS结构1.2 SDS与C字符串的区别1.2.1 获取字符串长度的时间复杂度是O(1)1.2.2 杜绝缓冲区溢出1.2.3 减少修改字符串时带来的内存重分配次数1.2.4 二进制安全1.2.5 兼容部分C字符串函数二、链表2.1 节点结构2.2 链表结构三、字典3.1 字典的实现哈希节点哈希表字典3.2 链地址法存储3.3 收缩与扩容rehash3.4 扩容或收缩步骤3.5 渐进式rehash渐进式rehash的步骤:总结说明四、跳跃表4.1 有序链表4.2 跳跃表 阅读详情

此文参考《Redis设计与实现》做出的总结

底层数据结构

SDS(简单动态字符串)

在Redis也会有一些字符串字面量,也就是不会进行修改的字符串使用C语言的字符串,即以空字符串结尾的字符数组。但为了修改的方便,Redis自行构建了一种数据结构用来保存可修改的字符串。

一个SDS结构体中,有三个变量分别是len用来记录当前保存的字符串长度,free用来记录未使用的字节量,buf字符数组用来保存字符串。这样做的优点是:

  • 以O(1)复杂度来获取字符串长度len

  • 杜绝缓冲区溢出,每次给字符串后添加字符时会通过free来确定SDS是否有足够的空间容纳,如果不够会自动扩展空间

  • 减少内存重分配次数,C字符串每次修改如果空间不够都将导致字符串重新分配内存比较耗时,而SDS通过空间预分配和惰性空间释放来减少内存重分配。空间预分配指当修改后SDS长度小于1MB时,那么程序将多分配一倍的空间预留给SDS,例如修改后len为13那么free也将是13,之后如果再在SDS后进行添加字符大概率free是够用的,大于1MB预留1MB时;惰性空间释放指当字符串修改后长度变短时并不进行内存重分配,而是将多出来的空间预留下来,用free记录预留空间,SDS也提供了相应的API,让我们可以在有需要时,真正地释放SDS的未使用空间,避免内存浪费

  • 二进制安全,C字符串中的字符必须符合某种编码且只能末尾为空字符,而SDS可以随意存取,当buf数组中有多个空字符时也不会影响(C字符串碰到空字符便认为字符串结束),因为SDS使用len判断字符串是否结束

  • 兼容部分C字符串函数,SDS仍然遵循C字符串以空字符结尾的惯例,为了重用C字符串函数

map(字典)

字典使用哈希表作为底层结构,使用拉链法处理哈希冲突,为了速度总是将新节点加到表头。字典中有两个哈希表,一般情况只使用哈希表1,在rehash时会同时使用两个哈希表。

rehash步骤:

  1. 为字典的ht[1]哈希表分配空间。如果执行的是扩展操作,那么ht[1]的大小为第一个大于等于ht[0].used*2的2的n次方幂,如果执行的是收缩操作,那么ht[1]的大小为第一个大于等于ht[0].used的2的n次方幂
  2. 将保存在ht[0]中的所有键值对rehash到ht[1]上面
  3. 当ht[0]包含的所有键值对都迁移到了ht[1]之后(ht[0]变为空表),释放ht[0],将ht[1]设置为ht[0],并在ht[1]新创建一个空白哈希表,为下一次rehash做准备

Redis的rehash是渐进式rehash,并不是一次性完成所有的rehash操作,这是采用分而治之的思想,为了防止rehash对服务器性能造成影响,将操作均摊到每次对字典的操作上。渐进式rehash操作:

  1. 在字典中维持一个索引计数器变量rehashidx,并将它的值设置为0,表示rehash工作正式开始。
  2. 在rehash进行期间,每次对字典执行添加、删除、查找或者更新操作时,程序除了执行指定的操作以外,还会顺带将ht[0]哈希表在rehashidx索引上的所有键值对rehash到ht[1],当rehash工作完成之后,程序将rehashidx属性的值增一。
  3. 随着字典操作的不断执行,最终在某个时间点上,ht[0]的所有键值对都会被rehash至ht[1],这时程序将rehashidx属性的值设为-1,表示rehash操作已完成。

渐进式rehash期间执行增删改查

  • 查找一个键的话,程序会先在ht[0]里面进行查找,如果没找到的话,就会继续到ht[1]里面进行查找,诸如此类。
  • 修改和删除一个键由于首先要查找到这个键,故和查找一样
  • 添加到字典的键值对一律会被保存到ht[1]里面,而ht[0]则不再进行任何添加操作,这一措施保证了ht[0]包含的键值对数量会只减不增,并随着rehash操作的执行而最终变成空表。

linkedlist(链表)

和数据结构的链表实现方式一样,是一个双向链表

skiplist(跳跃表)

基本介绍

跳跃表是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。

  • 跳跃表支持平均O(logN)、最坏O(N)复杂度的节点查找,还可以通过顺序性操作来批量处理节点。
  • 在大部分情况下,跳跃表的效率可以和平衡树相媲美,并且因为跳跃表的实现比平衡树要来得更为简单,所以有不少程序都使用跳跃表来代替平衡树。

跳跃表对象结构:

typedef struct zskiplist {
   
   
    // 头节点,尾节点
    struct zskiplistNode *header
Redis之数据结构 Redis 为什么那么快?除了它是内存数据库,使得所有的操作都在内存上进行之外,还有一个重要因素,它实现的数据结构,使得我们对数据进行增删查改操作时,Redis 能高效地处理。因此,这次我们就来好好聊一下 Redis 数据结构:String(字符串)对象、List(列表)对象、Hash(哈希)对象、Set(集合)对象和 Zset(有序集合)。底层(3.0和3.2之后有变化)对应的分别是:SDS、双向链表、压缩列表、哈希表、跳表、整数集合、quicklist、listpack。 阅读详情

相关推荐

莫比乌斯反演

本文从算法竞赛和数论角度出发,系统介绍了狄利克雷卷积与莫比乌斯反演的核心概念。首先定义了数论函数及其基本性质,重点阐述了狄利克雷卷积的代数结构(交换环)和关键恒等式(如μ*1=ε)。随后通过卷积视角简化了莫比乌斯反演的证明过程。最后将理论提升至抽象代数层面,揭示这些数论工具本质上是偏序集关联代数在整除关系下的特例,其中莫比乌斯函数对应Zeta函数的逆元。全文展现了数学概念从具体到抽象的升华过程,为理解这些工具提供了更深刻的代数视角。

aichitang2024的博客 392

SimpleITK图像基础(一)——3D Resampling

文章目录前言基于SimpleITK进行实现 前言 进入深度学习网络之前需要进行统一数据集,这个时候需要对这些数据集进行重新采样,即假设各向同性体素并重新定向它们,以便可以读取所有图像的像素矩阵。 在将方位变换成一致时,可以用DICOMOrientImageFilter过滤器,可以将 DesiredCoordinateOrientation设置为你想要变换的方位,它将计算出所需的置换顺序并根据需要执行翻转以接近所需方向。 基于SimpleITK进行实现 workflow如下: step 1:首先运行DICOM

YYY_77的博客 2019

使用 Cynthion 与 Packetry 进行 USB 抓包与协议分析

Cynthion 是 Great Scott Gadgets 推出的USB 流量分析与注入设备。它具备以下特点:通过 FPGA 实现高速 USB 流量捕获;能够同时作为 USB Host 和 Device,进行调试和测试;支持输出 pcap 文件,可直接用 Wireshark 分析;提供 Python API,方便与上层软件联动。简单来说,Cynthion 是一个USB 协议分析仪 + 注入工具。硬件层捕获:实时拦截 USB 总线上的数据包;软件层解析。

YIMUleizi的博客 1264

【教程4>第4章>第22节】FFT频偏估计方法,导频+cordic频偏估计方法,costas环的性能对比

频偏范围适应性:Costas 环频偏锁定和基于 PN 导频和 CORDIC 算法的频偏估计都可以通过调整参数来适应一定范围的频偏,但 Costas 环的频率捕获范围相对较窄,而基于 PN 导频和 CORDIC 算法的频偏估计,基于 FFT 变换频偏估计对频偏范围较大。在高信噪比条件下,三种方法都可以获得较高的估计精度,但在低信噪比环境中,基于 PN 导频和 CORDIC 算法的频偏估计,基于 FFT 变换频偏估计这两个开环方案相对更具优势,而Costas 环频偏锁定的精度可能会受到较大影响.

FPGA/MATLAB学习教程/源码/项目合作开发 610

手把手教你学Simulink实例:基于Simulink的超级电容器充放电仿真

超级电容器(Supercapacitor)是一种高容量电容器,具有快速充放电能力、长寿命和高功率密度等优点。它在能量存储系统、电动汽车、不间断电源(UPS)等领域有广泛应用。为了更好地理解和设计超级电容器的应用系统,通常需要进行详细的仿真分析。Simulink 提供了一个强大的仿真环境,可以用来设计、分析和验证超级电容器充放电系统的控制策略。本教程将详细介绍如何使用 Simulink 进行超级电容器充放电的仿真实例。通过本教程,我们详细介绍了如何使用 Simulink 进行超级电容器充放电的仿真实例。

MHD0815的博客 581

【Windows Server 2019】组策略的配置与管理——理论基础

博文介绍了组策略的定义,作用和分类。组策略包括计算机配置和用户配置;组策略又分为为基于本地的组策略和基于AD(活动目录)的域组策略。并说明了不同组策略发生冲突时默认的规则。

VMware, Windows, Linux, Cisco, Container, Kubernetes, Kali 1万+

C#串口通信从入门到精通(7)——整数/浮点数与二进制、八进制、十六进制之间的转换与C#实现

本文详细介绍由博主开发的DataConvert串口通信帮助类的用法,该帮助类涵盖了串口通信领域所有的数据转换方法,帮助大家快速编写串口通信程序!

qq_34059233的博客 2880

[关系图谱] 二.Gephi导入共线矩阵构建作者关系图谱

本文主要讲解Gephi绘制作者间的关系图谱,该软件可以广泛应用于社交网络、知识图谱分析,推荐读者使用。这是非常基础的一篇文章,重点讲解Gephi使用方法,希望对大家有所帮助。

杨秀璋的专栏 1万+

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

上一篇: 建造者模式
下一篇: 【日常实习】字节幸福里后台研发
荼锦AI编程
博客等级 码龄7年 198粉丝 27原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值