Redis五种数据结构底层编码结构

RedisObject

Redis中的任意数据类型的键和值都会被封装为一个RedisObject,也叫做Redis对象,源码如下:
image-20230614222235301

对象头不包含数据就已经占16字节,如果数据存string型,一个string一个对象头比较浪费空间,存大量数据时还是建议使用集合,这样可以共用一个对象头更加节省空间

Redis的编码方式

Redis中会根据存储的数据类型不同,选择不同的编码方式,共包含11种不同类型

image-20230614222443327

Redis中会根据存储的数据类型不同,选择不同的编码方式。 每种数据类型的使用的编码方式如下:

image-20230614222556047

String

String是Redis中最常见的数据存储类型:

  • 其基本编码方式是RAW,基于简单动态字符串(SDS)实现,存储上限为512mb。
  • 如果存储的SDS长度小于44字节,则会采用EMBSTR编码,此时object head与SDS是一段连续空间。申请内存时只需要调用一次内存分配函数,效率更高。(redis分配内存按2^n字节分配,当SDS占44字节时,object head与SDS占用64字节,不会产生内存碎片)
  • 如果存储的字符串是整数值,并且大小在LONG_MAX范围内,则会采用INT编码:直接将数据保存在RedisObject的ptr指针位置(刚好8字节,可以存储任意大小整数),不再需要SDS了。

整体结构:

image-20230614224132048

查看数据编码方式 object encoding key

image-20230614224556776

List

Redis的List类型可以从首、尾操作列表中的元素(列表左右两边都可以push、pop):

image-20230618234915017

满足上述功能的数据结构有如下三种:

  • LinkedList :普通链表,可以从双端访问,内存占用较高,内存碎片较多
  • ZipList :压缩列表,可以从双端访问,内存占用低,存储上限低
  • QuickList:LinkedList + ZipList,可以从双端访问,内存占用较低,包含多个ZipList,存储上限高

具体实现:

  • 在3.2版本之前,Redis采用ZipList和LinkedList来实现List,当元素数量小于512并且元素大小小于64字节时采用ZipList编码,超过则采用LinkedList编码。

  • 在3.2版本之后,Redis统一采用QuickList来实现List:

  • image-20230618235815242

    (where参数区分从头或者尾添加元素)

整体结构:

image-20230619000146331

Set

Set是Redis中的单列集合,满足下列特点:

  • 不保证有序性
  • 保证元素唯一
  • 求交集、并集、差集

image-20230619000646427

上述特点基本都需借助元素是否存在功能,满足快速高效判断元素是否存在数据结构如下:

  • HashTable,也就是Redis中的Dict,不过Dict是双列集合(可以存键、值对)【SkipList跳表有序因此不满足】

具体实现:

Set是Redis中的集合,不一定确保元素有序,可以满足元素唯一、查询效率要求极高。

  • 为了查询效率和唯一性,set采用HT编码(Dict)。Dict中的key用来存储元素,value统一为null
  • 存储的所有数据都是整数,并且元素数量不超过set-max-intset-entries时,Set会采用IntSet编码,以节省内存。

image-20230619001045392

添加元素IntSet可能会转为Dict

image-20230619001116343

整体结构:

image-20230619001423097

ZSet

ZSet也就是SortedSet,其中每一个元素都需要指定一个score值和member值:

image-20230625230456785

有如下特点:

  • 可以根据score值排序后
  • member必须唯一
  • 可以根据member查询分数

zset底层数据结构必须满足键值存储、键必须唯一、可排序这几个需求,如下两个编码结构满足需求:

  • SkipList:可以排序,并且可以同时存储score和ele值(member)
  • HT(Dict):可以键值存储,并且可以根据key找value

两者结合才能满足所有需求。

源码

image-20230625230738577

完整结构

image-20230625230822478

操作效率是很高,但是占用内存较大,每个元素存储两份

当元素数量不多时,HT和SkipList的优势不明显,而且更耗内存。因此zset还会采用ZipList结构来节省内存,不过需要同时满足两个条件:

① 元素数量小于zset_max_ziplist_entries,默认值128

② 每个元素都小于zset_max_ziplist_value字节,默认值64

image-20230625231139365

添加元素ZipList可能转化为SkipList(ZSet编码转换)

image-20230625231340888

ziplist本身没有排序功能,而且没有键值对的概念,因此需要有zset通过编码实现

  • ZipList是连续内存,因此score和element是紧挨在一起的两个entry, element在前,score在后
  • score越小越接近队首,score越大越接近队尾,按照score值升序排列

image-20230625231527876

Hash

Hash结构与Redis中的Zset非常类似:

  • 都是键值存储
  • 都需求根据键获取值
  • 键必须唯一

image-20230625231847870

区别如下:

  • zset的键是member,值是score;hash的键和值都是任意值
  • zset要根据score排序;hash则无需排序

因此,Hash底层采用的编码与Zset也基本一致,只需要把排序有关的SkipList去掉即可

  • Hash结构默认采用ZipList编码,用以节省内存。 ZipList中相邻的两个entry 分别保存field和value

  • 当数据量较大时,Hash结构会转为HT编码,也就是Dict,触发条件有两个:

    ① ZipList中的元素数量超过了hash-max-ziplist-entries(默认512)

    ② ZipList中的任意entry大小超过了hash-max-ziplist-value(默认64字节)

    image-20230625232929069

完整结构

image-20230625232114970

源码

添加元素

image-20230625232346854

是否进行编码转换

image-20230625232453233

最后插入元素(存在的更新不存在的新增)

image-20230625232626559

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

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

相关文章

Kafka系列之:对源连接器的的Exactly-Once支持

Kafka系列之:对源连接器的的Exactly-Once支持 一、背景二、目标三、公共接口四、连接器 API 扩展五、REST API验证六、新指标七、计划变更八、任务计数记录九、重新平衡的准备十、源任务启动十一、领导者访问配置主题十二、用于隔离事务生产者的管理 API十三、解决了…

python 加速(1)

文章目录 简单步骤像Python一样做torch 的一切安装Cmake安装 Torch (GPU)CMakeLists.txt试用小样设置 CLion 环境 Cuda配置VS C 环境建上手的文件step1: interpolation.cppstep2: interpolation_kernel.custep3: include/ utils.hstep4: setup.pystep5: …

redis和mysql

文章目录 一、redis1.1 redis的数据结构都有哪些?1.2 持久化方式有哪些?1.3 怎么保证缓存和数据库数据的一致性?1.4 redis缓存是什么意思? 二、数据库2.1 基本数据类型2.2 MySQL 的内连接、左连接、右连接有什么区别?2.3 MySQL 问题排查都有…

闲置iPad Pro打造真正的生产力工具!使用vscode编程写代码

文章目录 前言视频教程1. 本地环境配置2. 内网穿透2.1 安装cpolar内网穿透(支持一键自动安装脚本)2.2 创建HTTP隧道 3. 测试远程访问4. 配置固定二级子域名4.1 保留二级子域名4.2 配置二级子域名 5. 测试使用固定二级子域名远程访问6. iPad通过软件远程vscode6.1 创建TCP隧道 7…

Java阶段四Day08

Java阶段四Day08 文章目录 Java阶段四Day08关于pom.xml中的版本关于Session关于Token关于JWT在项目中使用JWTCustomUserDetailsUserDetailServiceImplUserServiceImpl 关于pom.xml中的版本 查看<groupId> 是同一家的只需配一个版本号<version><artifactId>中…

Spring Boot中的Profile:原理、用法与示例

Spring Boot中的Profile&#xff1a;原理、用法与示例 前言 Spring Boot 是一个快速开发 Spring 应用程序的框架&#xff0c;它提供了很多有用的功能和特性。其中&#xff0c;Profile 是一个常用的功能&#xff0c;它可以根据不同的环境配置来加载不同的配置文件&#xff0c;…

双路高速 DA 实验

目录 双路高速 DA 实验 1、简介 2、实验任务 3、程序设计 3.1、hs_dual_da顶层模块代码 3.2、ROM 波形存储模块&#xff08;rom_1024x10b&#xff09; 创建单端口 ROM IP核 3.2、DA 数据发送模块&#xff08;da_wave_send&#xff09;代码 4、硬件设计 4.1、添加.xdc…

Nginx网站服务

目录 Nginx简介 简述Nginx和Apache的差异 3 Nginx 相对于 Apache 的优点 阻塞与非阻塞 同步与异步 ginx 应用场景 nginx编译安装 Nginx安装和升级 1.关闭防火墙&#xff0c;将安装nginx所需软件包传到/opt目录下 2.拖入软件包 3.安装依赖包 3.创建运行用户与组 5.编译安…

【黑马头条-Java微服务项目】

黑马头条-Java微服务项目 (一)、项目介绍1.项目背景介绍(1).基本介绍(2).业务说明(3).项目术语介绍 2.技术栈说明(1).技术栈-基础六层技术(2).技术栈-服务四层技术(3).技术栈-分布 (二)、nacos环境搭建 (一)、项目介绍 1.项目背景介绍 (1).基本介绍 随着智能手机的普及&…

调用百度文心AI作画API实现中文-图像跨模态生成

作者介绍 乔冠华&#xff0c;女&#xff0c;西安工程大学电子信息学院&#xff0c;2020级硕士研究生&#xff0c;张宏伟人工智能课题组。 研究方向&#xff1a;机器视觉与人工智能。 电子邮件&#xff1a;1078914066qq.com 一&#xff0e;文心AI作画API介绍 1. 文心AI作画 文…

Seata 四种模式对比总结

一、前言 通过以下系列章节&#xff1a; docker-compose 实现Seata Server高可用部署 | Spring Cloud 51 Seata AT 模式理论学习、事务隔离及部分源码解析 | Spring Cloud 52 Spring Boot集成Seata利用AT模式分布式事务示例 | Spring Cloud 53 Seata XA 模式理论学习、使用…

Day_56-57kMeans 聚类

目录 Day_56-57 k-Means 聚类 一. 基本概念介绍 二. 具体过程 三. 代码实现与解释 1. 导入数据与数据初始化 2. 核心代码 3. 后续信息的补充 4. 距离计算和随机排列 四. 后续的数据分析 五. 运行结果 Day_56-57 k-Means 聚类 一. 基本概念介绍 同我上一篇博客的介绍&…