当前位置: 首页 > news >正文

Redis集合底层实现原理

目录

  • 本章重点
  • 简单动态字符串SDS
  • 集合底层实现原理
    • zipList
    • listPack
    • skipList
    • quickList
    • Key 与Value中元素的数量

本章重点

  • 掌握Redis简单动态字符串
  • 了解Redis集合底层实现原理

简单动态字符串SDS

  • SDS简介

我们Redis中无论是key还是value其数据类型都是字符串.我们Redis中的字符串是如何存储的呢?虽然我们的Redis是用C语言开发的,但是并没有直接套用其字符串形式.自定义了一种字符串.这种字符串结构简单,功能强大,称为简单动态字符串(Simple Dynamic String) 简称SDS
Redis中的字符串并非都是SDS,字面常量是C字符串

  • SDS结构

SDS是一个结构体,定义在Redis安装目录下的src/sds.h

sturct sdshdr
{//字节数组,用于保存字符串char buf[];//buf[]中已使用的字节数量,称为SDS长度int len;//buf[]中尚未使用的字节数量int free; 
}

我们可以查看src/sds.h定义
在这里插入图片描述

例如我们执行一个set name "hello redis"命令时,这里的字符串是字面常量,在Redis存储方式如下:

在这里插入图片描述

这里的\0是需要储存在buf中的,但是不记录长度len!

  • SDS优势
  • 字符串长度获取性能高,无需遍历字符串
  • 保证二进制安全,我们的C字符串真能在字符串结尾出现\0,而在图片,音频,视频等二进制文件数据以\0作为分隔符情况很是常见,所以C字符串无法保存其二进制数据,而SDS可以通过len判断字符串结尾位置.读取到什么,就存储,无需其他过滤操作即可!
  • 减少内存再分配次数,SDS采用了空间预分配策略和惰性空间释放策略,来避免再分配空间问题!
    1.如果len<1M,那么free空间大小和len相同.
    2.len>=1M,free固定大小=1M
    如果sds长度len减小,那么free也不会释放,等到后期再次分配使用
    如需释放可以手工调用函数释放
  • 兼容C函数
    因为保留的C语言的\0我们的SDS也可以使用C语言字符串函数 strcmp等
  • 常用的SDS操作函数

在这里插入图片描述
在这里插入图片描述

集合底层实现原理

Redis中对于Set类型底层的实现,直接采用了hashTable,但是对于Hash,Zset,List集合的底层进行了特殊设计,保证Redis的高性能

  • 2种实现的选择

对于Hash和Zset集合,其底层实现实际有2种:压缩zipList和跳跃列表skipList
这两种实现,用户都是透明的,系统会根据用户写入数据的不同,选择不同的的实现.只有同时满足了配置文件redis.conf中配置d相关集合元素个阈值和元素大小阈值两个条件使用的就是压缩链表zipList.例如Zset集合满足下面2个条件就是zipList

  • 集合元素个数小于 redis.conf 中zset-max-ziplist-entries属性的值,其默认值为 128
  • 每个集合元素大小都小于 redis.conf 中 zset-max-ziplist-value 属性的值,其默认值为 64字节

zipList

  • zipList
    在这里插入图片描述
    zipList通常称为压缩链表,是经过特殊编码的用于存储字符串或整数的的双向链表.其底层由3部分构成!
    head,entries,end.这3部分在空间上是连续存放的.

    • head

    head由3部分构成:

    • zlbytes:占4个字节,用于存放整个ziplist的数据结构所占字节数,包括zlbytes本身长度!
    • zltail:占用4个字节,用于存放最后一个entry在整个数据结构的偏移量(字节)可以快速定位列表尾位置,以便操作!
    • zllen:占2个字节,用于存放列表包含的entry个数,由于只有16位,所有最多ziplist只能有65535个entry
    • entries

    entries是真正的列表,由很多的entry元素构成,由于不同的元素类型,数值的不同,从而导致entries的长度不同,entry也由3部分构成

    • prevlength:记录上一个entry的长度,用于实现逆序遍历,默认长度为1个字节,如果上一个entry长度大于了254字节,prevlength就会扩展到3个字节
    • encoding:该部分用于标志后面的data数据类型,如果data是整数,encoding部分长度为1个字节,如果是字符串类型,那么可能为1个字节/2/5个字节长度,由于data数据长度的不同对应的encoding长度也不同.
    • end

    end自包含一部分zlend占1个字节,是ziplist的结束标志. 二进制8个1固定255!

listPack

  • listPack

对于我们的ziplist的entry结构,由于其实现的逆序遍历,保存了前一个entry的大小,如果进行了中间修改或者插入操作,会导致级联更新,影响性能.为了实现更紧凑,更快解析,更简单的实现,重写了实现了ziplist命名为listPack.
在Redis7.0已经将zipList全部替换成了listPack,为了兼容保留了zipList的相关属性!

在这里插入图片描述

listPack结构

listPack是经过特殊编码的用于存储字符串或整数的双向链表.底层数据结构也由其3部分构成!

  • head

head由2部分构成:

  • totalBytes:占4个字节,用于存放listPack整个数据结构包含其本身长度,单位是字节
  • elemNum:占2个字节,用于保存entry元素个数,最多为65535个!
  • entry

这里就是和zipList的区别之处,这里没有了prevlength,增加了记录当前长度的element-total-len也可实现逆序遍历.而不会引发级联更新

  • encoding:该部分用于标志后面的data的具体类型。如果data为整数类型,encoding 长度可能会是1、2、3、4、5或9字节。不同的字节长度,其标识位不同。如果data 为字符串类型,则encoding长度可能会是1、2或5字节。data字符串不同的长度,对应着不同的encoding长度。
  • data:真正存储数据的位置,整数或者字符串类型,不同数据占用的字节长度不同
  • element-total-len:记录当前entry长度,用于实现逆序遍历.可能的值[1,5]字节
  • end

这里的end和zlend一样,都是结束标志,255,8个二进制1构成

skipList

  • skipList

跳跃列表,简称跳表,是一种随机化的数据结构,基于并联的链表.实现简单,查询效率高.就是链表的一种不过在此基础上实现了跳跃功能.使得在查找元素具有较高的速率!

  • 原理

在这里插入图片描述
skipList就是在list基础上随机增加一些高层指针,高层指针遍历效率高,层级越高,查找效率越高!我们可以先在高层遍历,然后再向下层级遍历查找指定位置

  • 算法优化

这里的层级采用随机的方式,就有效的避免了按照指定规定元素个数的层级方式,插入或修改元素需要对链表的层级指针进行修改!而采用随机层级的方式就插入元素就随机层级,然后插入即可,删除也修改前后指针即可!

quickList

  • quickList

快速链表,quickList本身是一个双向无循环链表.他的每一个节点都是一个zipList.由于zipList和linkedList都有明显不足,而quickList就进行了改进操作!
在这里插入图片描述

  • 检索操作

我们的quickList可以通过zipList中head部分记录的totalNum进行检索!对其遍历的zipList的entry进行求和从而定位到指定的zipList的entry元素

  • 插入操作
//设插入元素大小为: insertB
//查找到的插入位置元素大小为: zlB 
//zipList最大值: zpMax 
//前(后)一个元素大小: plB/nlB
1. insertB+zlB<=zpMax:
//直接插入zipList相应位置即可
2. insertB+zlB>zpMax 并且插入的位置位于元素首部位置
//2.1 insertB+plB<=zpMax:直接插入前一个元素尾部
//2.2 insetB+plB >zpMax: 构建一个新元素zipList然后连接到quickList
3. insertB+zlB>zpMax 并且插入的位置位于元素尾部位置
//3.1 insertB+nlB<=zpMax:直接插入前一个元素首部
//3.2 insetB+nlB >zpMax: 构建一个新元素zipList然后连接到quickList
4. insertB+zlB>zpMax 并且插入位置位于中间
//将当前zipList分割为2个zipList连接到quickList中,然后将元素插入到分割后的前一个元素的尾部位置
  • 删除操作

直接删除即可,如果当前zipList已经没有元素了,就将当前zipList删除即可,然后修改指针连接

Key 与Value中元素的数量

  • Redis最多可以处理2^32个key(42亿) 实际每个Redis实例可以处理至少2.5亿个key
  • 每个Hash,List,Set,ZSet集合都可以包含2^32个元素

相关文章:

Redis集合底层实现原理

目录 本章重点简单动态字符串SDS集合底层实现原理zipListlistPackskipListquickListKey 与Value中元素的数量 本章重点 掌握Redis简单动态字符串了解Redis集合底层实现原理 简单动态字符串SDS SDS简介 我们Redis中无论是key还是value其数据类型都是字符串.我们Redis中的字符…...

OVS常用命令与使用总结

OVS常用命令与使用总结 说明 在平时使用ovs中&#xff0c;经常用到的ovs命令&#xff0c;参数&#xff0c;与举例总结&#xff0c;持续更新中… 进程启动 1.先准备ovs的工作目录&#xff0c;数据库存储路径等 mkdir -p /etc/openvswitch mkdir -p /var/run/openvswitch …...

一以贯之:从城市网络到“城市一张网”

《论语里仁》中子曰&#xff1a;“参乎&#xff0c;吾道一以贯之”。 孔子所说的“一以贯之”&#xff0c;逐渐成为了中国文化与哲学的重要组成部分&#xff0c;指明事物发展往往需要以标准化、集约化、融合化作为目标。这种智慧在数字化发展中格外重要。从云计算、大数据技术模…...

【Java校招面试】基础知识(四)——JVM

目录 前言一、基础概念二、反射三、类加载器ClassLoader四、JVM内存模型后记 前言 本篇主要介绍Java虚拟机——JVM的相关内容。 “基础知识”是本专栏的第一个部分&#xff0c;本篇博文是第四篇博文&#xff0c;如有需要&#xff0c;可&#xff1a; 点击这里&#xff0c;返回…...

项目管理-计算专题(三点估算、PERT估算)

基本概念 通过考虑估算中的不确定性和风险&#xff0c;可以提高活动持续时间估算的准确性。这个概念源自计划评审技术(PERT)。PERT使用三种估算值来界定活动持续时间的近似区间: 最可能时间(tM)&#xff1a;基于最可能获得的资源、最可能取得的资源生产率、对资源可用时间的现…...

【华为OD机试 2023最新 】模拟商场优惠打折(C语言题解 100%)

文章目录 题目描述输入描述输出描述用例题目解析代码思路C语言题目描述 模拟商场优惠打折,有三种优惠券可以用,满减券、打折券和无门槛券。 满减券:满100减10,满200减20,满300减30,满400减40,以此类推不限制使用; 打折券:固定折扣92折,且打折之后向下取整,每次购…...

使用TrieTree(字典树)来实现敏感词过滤

使用TrieTree&#xff08;字典树&#xff09;来实现敏感词过滤 1. 字典树定义 字典树&#xff08;TrieTree&#xff09;&#xff0c;是一种树形结构&#xff0c;典型应用是用于统计&#xff0c;排序和保存大量的字符串&#xff08;但不仅限于字符串,如01字典树&#xff09;。…...

USB转串口芯片CH9101U

CH9101是一个USB总线的转接芯片&#xff0c;实现USB转异步串口。提供了常用的MODEM联络信号&#xff0c;用于为计算机扩展异步串口&#xff0c;或者将普通的串口设备或者MCU直接升级到USB总线。 特点 全速USB设备接口&#xff0c;兼容USB V2.0。内置固件&#xff0c;仿真标准串…...

Java语言介绍

Java是一种广泛使用的计算机编程语言&#xff0c;由Sun Microsystems公司于1995年推出。它是一个健壮的、面向对象的、跨平台的语言&#xff0c;被用于开发各种应用程序和系统&#xff0c;包括Web应用程序、移动应用程序、桌面应用程序、游戏以及企业级系统等。 Java具有许多优…...

终于把 vue-router 运行原理讲明白了(二)!!!

一、vue-router路由变化侦测 1.1 上一遍文章中&#xff0c;介绍了vue-router 的install 函数的内部实现&#xff0c;知道了能在this中访问$router 和视图更新的机制&#xff0c;文章链接终于把 vue-router 运行原理讲明白了&#xff08;一&#xff09;&#xff01;&#xff01…...

ChatGPT实现服务器体验沙箱

服务器体验沙箱 IT 人员在学习一门新技术时&#xff0c;第一个入门门槛通常都是"如何在本地安装并成功运行"。因此&#xff0c;很多技术的官网都会通过沙箱技术&#xff0c;提供在线试用的 playground 或者按步模拟的 tour。让爱好者先在线尝试效果是否满足预期&…...

【算法】刷题中的位运算

作者&#xff1a;指针不指南吗 专栏&#xff1a;算法篇 &#x1f43e;人类做题的过程&#xff0c;其实是暴搜的过程&#x1f43e; 文章目录 1.位运算概述2.位运算符3.位运算应用3.1整数的奇偶性判断3.2有关 2 的幂的应用3.3lowbit(x)返回x的最后一位13.4二进制数中1的个数3.5求…...

9.Java中异常处理机制是什么

Java的异常处理通过五个关键字来实现&#xff0c;分别是捕获异常&#xff1a;try&#xff0c;catchsfinally&#xff1b;声明异常&#xff1a;throws&#xff1b;抛出异常&#xff1a;throw 一&#xff1a;try&#xff0c;catch捕获异常二&#xff1a;finally回收资源三&#x…...

GeoTools实战指南: 叠加GeoTIFF与Shapefile图层生成截图

GeoTools实战指南: 叠加GeoTIFF与Shapefile图层生成截图 介绍 本教程将介绍如何使用GeoTools库在Java中将栅格数据(GeoTIFF)与矢量数据(Shapefile)叠加显示,并将结果保存为PNG格式的图片文件。我们将解析和分析 RasterDataRenderer 类,并了解其中的每个方法和对象。 准…...

nginx配置sh脚本远程执行一键安装

背景 本地多机重复操作某些shell指令&#xff0c;分步执行&#xff0c;很耗费时间&#xff0c; 需要远程一键部署&#xff0c;傻瓜化运维&#xff0c;更为通用安装。 即参考docker通用安装 sudo curl https://get.docker.com | sh - # sudo python3 -m pip install docker-co…...

Excel表格成绩排名全攻略,让你事半功倍!

在学校或公司中&#xff0c;我们经常需要对成绩进行排名。如果手动计算排名&#xff0c;不仅费时费力&#xff0c;而且容易出错。幸运的是&#xff0c;Microsoft Excel提供了一个简单而快速的方法来计算和显示排名。 在学校或公司中&#xff0c;成绩排名是一项重要的任务。使用…...

Docker 持久化存储 Bind mounts

Docker 持久化存储 Bind mounts Bind mounts 的 -v 与 --mount 区别启动容器基于bind mount挂载到容器中的非空目录只读 bind mountcompose 中使用 bind mount 官方文档&#xff1a;https://docs.docker.com/storage/bind-mounts/ Bind mounts 的 -v 与 --mount 区别 如果使用…...

LVS +Keepalived 高可用群集部署

一、LVSKeepalived 高可用群集 在这个高度信息化的 IT 时代&#xff0c;企业的生产系统、业务运营、销售和支持&#xff0c;以及日常管理等环节越来越依赖于计算机信息和服务&#xff0c;对高可用&#xff08;HA&#xff09;技术的应用需求不断提高&#xff0c;以便提供持续的…...

Kafka调优

生产者 参数名称描述bootstrap.serverskafka集群的地址key.deserializerkey的反序列化类&#xff0c;写全类名value.deserializervalue的反序列化类&#xff0c;写全类名buffer.memoryRecordAccumulator缓冲区总大小&#xff0c;默认32mbatch.size缓冲区一批数据最大值&#x…...

Debezium系列之:详细介绍Debezium2.X版本导出Sqlserver数据库Debezium JMX指标的方法

Debezium系列之:详细介绍Debezium2.X版本导出Sqlserver数据库Debezium JMX指标的方法 一、需求背景二、相关技术文章三、安装jmx_prometheus_javaagent四、Debezium2.X版本Sqlserver数据库jmx指标格式五、导出Debezium2.X版本Sqlserver数据库jmx指标方法六、Debezium2.X版本各…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...

CTF show 数学不及格

拿到题目先查一下壳&#xff0c;看一下信息 发现是一个ELF文件&#xff0c;64位的 ​ 用IDA Pro 64 打开这个文件 ​ 然后点击F5进行伪代码转换 可以看到有五个if判断&#xff0c;第一个argc ! 5这个判断并没有起太大作用&#xff0c;主要是下面四个if判断 ​ 根据题目…...

ubuntu中安装conda的后遗症

缘由: 在编译rk3588的sdk时&#xff0c;遇到编译buildroot失败&#xff0c;提示如下&#xff1a; 提示缺失expect&#xff0c;但是实测相关工具是在的&#xff0c;如下显示&#xff1a; 然后查找借助各个ai工具&#xff0c;重新安装相关的工具&#xff0c;依然无解。 解决&am…...

OpenGL-什么是软OpenGL/软渲染/软光栅?

‌软OpenGL&#xff08;Software OpenGL&#xff09;‌或者软渲染指完全通过CPU模拟实现的OpenGL渲染方式&#xff08;包括几何处理、光栅化、着色等&#xff09;&#xff0c;不依赖GPU硬件加速。这种模式通常性能较低&#xff0c;但兼容性极强&#xff0c;常用于不支持硬件加速…...

STL 2迭代器

文章目录 1.迭代器2.输入迭代器3.输出迭代器1.插入迭代器 4.前向迭代器5.双向迭代器6.随机访问迭代器7.不同容器返回的迭代器类型1.输入 / 输出迭代器2.前向迭代器3.双向迭代器4.随机访问迭代器5.特殊迭代器适配器6.为什么 unordered_set 只提供前向迭代器&#xff1f; 1.迭代器…...

【RabbitMQ】- Channel和Delivery Tag机制

在 RabbitMQ 的消费者代码中&#xff0c;Channel 和 tag 参数的存在是为了实现消息确认机制&#xff08;Acknowledgment&#xff09;和精细化的消息控制。 Channel 参数 作用 Channel 是 AMQP 协议的核心操作接口&#xff0c;通过它可以直接与 RabbitMQ 交互&#xff1a; 手…...

【Linux应用】Linux系统日志上报服务,以及thttpd的配置、发送函数

【Linux应用】Linux系统日志上报服务&#xff0c;以及thttpd的配置、发送函数 文章目录 thttpd服务安装thttpd配置thttpd服务thttpd函数日志效果和文件附录&#xff1a;开发板快速上手&#xff1a;镜像烧录、串口shell、外设挂载、WiFi配置、SSH连接、文件交互&#xff08;RADX…...