Redis从入门到精通【高阶篇】之底层数据结构压缩列表(ZipList)详解

news2024/11/30 6:55:22

👏 简介:大家好,我是冰点,从业11年,目前在物流独角兽企业从事技术管理和架构设计方面工作,之前的把博客作为技术流水账在写。现在准备把多年的积累整理一下,成体系的分享给大家,也算是对多年开发生涯的总结。如果你在工作和学习中遇到问题也可反馈给我(iceicepip), 路漫漫其修远兮,吾将上下而求索。
 
🏳️‍🌈2023计划:
             🚩1. 将多年来整理的Redis学习和实践笔记整理并发布成专栏。
             🚩2. 将最近2年在groovy实践应用上的沉淀的初稿,发布成书籍。
             🚩3. 将多年来整理的MySQL学习研究笔记整理并发布成专栏。
             🚩4. 根据技术交流群答疑的问题,整理成博客文章发布分享。

在这里插入图片描述

文章目录

    • 1. 压缩列表的结构
    • 2. 压缩列表的操作
    • 3. 压缩列表的优缺点
      • 3.1优点:
      • 3.2缺点:
    • 4. 总结
    • 5. 推荐阅读

前面的Redis从入门到精通的基础篇和进阶篇都是在使用层面和概念层面,本章节,我们了解一下redis的底层数据结构,上几个章节,我们讲了SDS,字典 。本章节我们聊一下ZipList。

压缩列表(ZipList)就是redis为了节约内存而设计开发的数据结构,并且作为列表键和哈希键的底层实现之一。Redis中的压缩列表(ZipList)是一种特殊的数据结构,用于存储一系列的连续元素。ZipList是Redis中的底层数据结构之一,常用于存储列表和哈希表等数据类型的底层实现。在本文中,我们将深入了解Redis中的压缩列表,包括ZipList的结构和操作等。

1. 压缩列表的结构

Redis中的压缩列表(ZipList)是由一系列的节点(entry)组成的。每个节点可以是一个字节数组(byte array)、一个整数或者一个指针。在ZipList中,每个节点的大小是不固定的,取决于节点所包含的数据类型和数据大小。ZipList中节点的个数也是不固定的,可以根据需要动态增加或减少。

ZipList的结构如下图所示:

+--------+--------+--------+--------+--+-----+
| zlbytes| zltail | zllen  |entry1  |..|entryN|
+--------+--------+--------+--------+--+-----+
  • zlbytes字段的类型是uint32_t, 这个字段中存储的是整个ziplist所占用的内存的字节数
  • zltail字段的类型是uint32_t, 它指的是ziplist中最后一个entry的偏移量. 用于快速定位最后一个entry, 以快速完成pop等操作
  • zllen字段的类型是uint16_t, 它指的是整个ziplit中entry的数量. 这个值只占2bytes(16位): 如果ziplist中entry的数目小于65535(2的16次方), 那么该字段中存储的就是实际entry的值. 若等于或超过65535, 那么该字段的值固定为65535, 但实际数量需要一个个entry的去遍历所有entry才能得到.
  • zlend是一个终止字节, 其值为全F, 即0xff. ziplist保证任何情况下, 一个entry的首字节都不会是255
    在这里插入图片描述

其中,zlbytes是压缩列表的长度(包括所有的字节),zltail是指向压缩列表尾部的指针,zllen是压缩列表中节点的个数,entry1到entryN是压缩列表中的所有节点。

###节点结构
在压缩列表中,每个节点的结构如下:

+--------+--------+
| prevlen| encoding| data  |
+--------+--------+

prevlen是前一个节点的长度(单位为字节),encoding是数据的编码方式,data是节点的实际数据。在压缩列表中,prevlen和encoding都是可选的。当节点的前一个节点的长度小于254字节时,prevlen字段被省略,encoding字段存储在数据之前,否则prevlen字段占用5个字节,encoding字段存储在prevlen后面的5个字节中。

根据不同的数据类型,压缩列表中节点的编码方式也有所不同,下面是常用的节点编码方式:

  • 字节数组(byte array):
+--------+--------+---------------+
| prevlen| 0xc000 |    length     |
+--------+--------+---------------+
|              data               |
+---------------------------------+

其中,0xc000是一个特殊的编码方式,用于标识节点存储的是字节数组。length是字节数组的长度,data是字节数组的实际数据。

  • 整数:
+--------+--------+--------+
| prevlen|  int   |   int  |
+--------+--------+--------+

其中,int是一个整数,可以是8位、16位或32位的有符号整数。

  • 指针:
+--------+--------+--------+
| prevlen|  0x01  |  ptr   |
+--------+--------+--------+

其中,0x01是一个特殊的编码方式,用于标识节点存储的是指针。ptr是一个指针,可以指向任意的内存地址。

2. 压缩列表的操作

Redis中的压缩列表支持以下常用的操作:

  • 压缩列表的创建
unsigned char *zl = ziplistNew();
  • 压缩列表的添加
zl = ziplistPush(zl, s, len, ZIPLIST_TAIL);

其中,s是一个字节数组,len是字节数组的长度,ZIPLIST_TAIL表示在压缩列表的尾部添加节点。

zl = ziplistPushInt(zl, value);

其中,value是一个整数,表示在压缩列表的尾部添加整数节点。

  • 压缩列表的删除
zl = ziplistDelete(zl, &p);

其中,p是一个指向要删除的节点的指针。

  • 压缩列表的遍历
unsigned char *p = ziplistIndex(zl, index);
unsigned char *entry = NULL;
unsigned int entry_len = 0;
long long entry_int = 0;
int ret = ziplistGet(p, &entry, &entry_len, &entry_int);

其中,index是节点的下标,p是指向节点的指针,entry是节点的数据(字节数组或整数),entry_len是字节数组的长度,entry_int是整数的值,ret表示节点的数据类型(字节数组或整数)。

  • 压缩列表的长度
unsigned int ziplistLen(unsigned char *zl);

以上是常用的压缩列表操作,还有其他的操作可以参考Redis源代码中的ziplist.h和ziplist.c文件。

3. 压缩列表的优缺点

3.1优点:

  • 紧凑的存储结构使得压缩列表的空间占用更小,可以在一定程度上减少内存碎片的发生。
  • 压缩列表支持动态增加和删除节点,可以随着数据的增长而自动扩容或缩容,不需要预先分配空间。
  • 压缩列表的节点采用紧凑的存储方式,使得节点访问和遍历的效率较高。同时,压缩列表支持从头和尾部两个方向同时遍历节点。

3.2缺点:

  • 节点大小不固定,当节点的大小随着数据的增长而不断变化时,可能会导致内存碎片的发生,从而增加了内存分配和释放的成本。
  • 压缩列表不支持快速的节点插入和删除操作,因为在插入或删除节点时,需要对后面的节点进行移动,会导致频繁的内存复制操作,从而影响性能。如果需要频繁进行插入和删除操作,建议使用链表等其他数据结构。
  • 压缩列表的节点的数据类型和大小有限制,不适合存储大量的大型数据。例如,压缩列表最大支持512MB的大小,单个节点最大支持64KB的大小,单个整数节点最大支持32位的有符号整数。如果需要存储大量的大型数据,建议使用其他数据结构,例如哈希表或有序集合。

4. 总结

本文详细介绍了Redis中的压缩列表(ZipList),包括ZipList的结构和操作等。压缩列表是Redis中的底层数据结构之一,常用于存储列表和哈希表等数据类型的底层实现。压缩列表具有紧凑的存储结构、支持动态增加和删除节点、支持快速的节点访问和遍历等优点,但也有节点大小不固定、不支持快速的节点插入和删除操作等缺点。在实际应用中,需要根据具体的需求选择合适的数据结构来存储数据。

5. 推荐阅读

如果想详细阅读源码解析推荐学习铁蕾的这篇文章
Redis内部数据结构详解(4)——ziplist

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

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

相关文章

阿里巴巴最新开源“SpringSecurity手册”用户+案例+认证+框架,面面俱到太全了

pringSecurity 相信Spring大家一定不陌生,那么SpringSecurity你又了解多少呢?市面上有关Spring的介绍有很多,那么对于SpringSecurity只有一些简单的有关概念的介绍,如果想深入了解并使用SpringSecurity还是需要下很大的功夫的&am…

Python爬取广州、深圳、河源、惠州四个城市天气数据,并作数据可视化

本文爬取的网站是天气,天气预报查询,24小时,今天,明天,未来一周7天,10天,15天,40天查询_2345天气王 1.爬取广惠河深2022-2024年的数据 import requests # 发送请求要用的模块 需要额外安装的 import parsel import csvf open(广-惠-河-深天气.csv, modea, encodingut…

【自学网安必看】自学网络安全遇到的问题及解决方法!

自学网络安全很容易学着学着就迷茫了,找到源头问题,解决它就可以了,所以首先咱们聊聊,学习网络安全方向通常会有哪些问题,看到后面有惊喜哦 1、打基础时间太长 学基础花费很长时间,光语言都有几门&#x…

STM32 HAL库开发——入门篇(1)

目录 一、GPIO 1.1 什么是GPIO 1.2 GPIO简介 1.2.1 GPIO特点 1.2.2 GPIO电气特性 1.2.3 GPIO引脚分布 1.3 IO端口基本结构介绍 1.4 GPIO的八种模式 1.5 GPIO的寄存器介绍 1.6 通用外设驱动模型(四步法) 1.7 GPIO配置步骤 1.8 编程实战…

用Notes打造一个资讯中心

大家好,才是真的好。 有一段时间,我介绍过,从Domino 10版本开始,LotusScript增强了网络数据访问和JSON解析功能等,从而可以从网上获取很多资讯,例如即时新闻、股市资讯等等。 例如我们采用Notes内置的讨论…

多线程-线程安全的懒汉式_死锁-ReentrantLock的使用

线程安全的懒汉式_死锁-ReentrantLock的使用 解决单例模式中的懒汉式的线程安全问题 解决单例模式中的懒汉式的线程安全问题> 饿汉式:不存在线程安全问题。 > 懒汉式:存在线程安全问题,(需要使用同步机制来处理&#xff0…

案例39:基于Java办公自动化管理系统开题报告设计

博主介绍:✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专…

Spring架构篇--2.7.3 远程通信基础--Netty原理--bind实现端口的绑定

前言:在对ServerBootstrap 进行属性赋值之后,通过bind 方法完成端口的绑定,并开始在NioEventLoop中进行轮询进行事件的处理;本文主要探究ServersocketChannel 在netty 中是如何完成注册,以及端口的绑定 1 Nio selecto…

两个月涨粉90万,B站内容风向又有新指示?

6月1日,B站公布了2023年第一季度财报。 财报中显示第一季度,B站日均活跃用户达9370万,同比增长18%。用户日均使用时长96分钟,日均视频播放量达41亿,其中,本季度B站Story-Mode竖屏视频日均播放量同比增长82…

网络安全怎么学?才不会成为脚本小子?

一,怎么入门? 1、Web 安全相关概念(2 周) 了解网络安全相关法律法规 熟悉基本概念(SQL 注入、上传、XSS、CSRF、一句话木马等)。 通过关键字(SQL 注入、上传、XSS、CSRF、一句话木马等&#…

Python使用WMI模块获取Windows系统的硬件信息,并使用pyinstaller库编译打包成exe的可执行文件

引言 今天给大家分享一篇有关Python和Windows系统的文章。你有没有想过如何获取Windows系统的硬件信息?或者你是否曾经尝试过将Python脚本编译打包成可执行文件?如果你对这些问题感兴趣,那么这篇文章一定适合你。 背景 由于公司现阶段大多…

软件兼容性测试怎么进行?兼容性测试有什么作用?

随着软件的不断更新和升级,兼容性测试也逐渐成为了软件测试的一项重要内容。那么,软件兼容性测试到底是什么?怎么进行?又有什么作用呢? 一、什么是软件兼容性测试? 软件兼容性测试是指在不同的操作系统、硬件设备、浏览器等多个环境下测试软件的可…

VulnHub项目:Hogwarts:Bellatrix

靶机地址:Hogwarts: Bellatrix ~ VulnHub 哈利波特系列~有趣~~~ 渗透过程: 首先获取靶机ip地址 对其端口探测 访问web端口,发现了小天狼星的堂姐Bellatrix Lestrange贝拉特里克斯莱斯特兰奇那个疯狂的女人!!&#x…

天涯直播筹资300万,七天仅赚14.99万,重启计划岌岌可危

我是卢松松,点点上面的头像,欢迎关注我哦! 天涯前天涯社区总编直播卖货欲筹300万,重启天涯。直播七天七夜只赚了14.99万。对于普通人来说,这收入真的是望尘莫及了,但对于天涯来说杯水车薪。 也许天涯部分…

前端工程化初体验

最近在尝试着完整地体验一下前端工程化需要的那些流程,于是自己尝试一套属于自己的前端工程化流程。 前端工程化需要做什么: 1、创建项目需要有项目模板资源,所以这里我创建了一个前端脚手架CLI工具,mfex-project,主…

Win10系统蓝屏如何使用U盘重装系统?

Win10系统蓝屏如何使用U盘重装系统?很多用户遇到了电脑系统蓝屏问题之后,都不知道怎么去进行系统重装的方法。其实系统重装没有大家想象的那么困难,以下为大家带来详细的图文教程分享。 准备工作: 1、U盘一个(尽量使用…

2023年5月CSDN客服月报|解决5个重大问题和18个次要问题,采纳1个用户建议,处理2个用户需求

听用户心声,解用户之需。hello,大家好,这里是《CSDN客诉报告》第20期,接下来就请大家一同回顾我们5月份解决的bug~ 一、重大问题 1、【商城】已支付订单权益未正常下发 反馈量:23 2、【UC】收藏/评论/账…

2023年湖北高考作文AI写

本文由 大侠(AhcaoZhu)原创,转载请声明。 链接: https://blog.csdn.net/Ahcao2008 2023年湖北高考作文AI写 🧊摘要🧊原题🧊解析🧊AIGCInsCode AI 创作助手文心一言讯飞星火 SparkDeskChatGPT3.5 🧊摘要 本文…

CANoe学习笔记一

目录 摘要 1、CANoe工程的新建 2、通过Trace工具查看交互的报文内容 3、通过Logging保存日志文件 4、创建IG发送报文 5、通过Graphics界面抓取信号波形 6、加载cdd文件 7、过滤报文ID的接收 8、其他 摘要 CANoe是德国Vector公司为汽车总线的开发而设计的一款总线开发环…

nuxt3.0学习-四、nuxt3.0的middleware(中间键)、composables(可组合物)以及Plugins(插件目录)

Nuxt3.0中间键了解地址 Nuxt提供了一个可定制的路由中间件框架,您可以在整个应用程序中使用它,非常适合在导航到特定路由之前提取要运行的代码; 路由中间件有三种: 匿名(或内联)路由中间件,直…