当前位置:网站首页> Redis ziplist 压缩列表的源码解析
Redis ziplist 压缩列表的源码解析
2022-06-30 19:18:00 【1024问】
前言
源码解读
ziplist 布局
entry 节点
prelen
encoding 编码
总结
前言相信对使用过 Redis 的人来说,数据类型 List 是不会陌生的吧。大多数人需要实现一个队列时候,首选的就是 List 了。但是其实 Redis 的 List 类型有多种实现方式。这篇文章就是介绍其中一种实现 ziplist - 压缩列表。
源码解读一如既往,关于 ziplist 的定义和实现还是放在一对文件中,分别是 ziplist.h 和 ziplist.c。在 ziplist.c 文件的头部有着这么一段注释介绍什么是 ziplist。
ziplist 是一个经过特殊编码的双向链表,旨在提高内存效率。 它存储字符串和整数值,其中整数被编码为实际整数而不是一系列字符。 它允许在 O(1) 时间内在列表的任一侧进行推送和弹出操作。 但是,由于每个操作都需要重新分配 ziplist 使用的内存,因此实际复杂性与 ziplist 使用的内存量有关。
从这段话得到:对于不同的数据类型有着不同的编码方式,理解为会对数据进行压缩,从而达到减少内存使用的目的。但是随着存储的 value 数据级增加,使用 ziplist 所付出的代价也随之增加。
ziplist 布局ziplist 是一个特殊双向链表,不像普通的链表使用前后指针关联在一起,它是存储在连续内存上的。整体的结构布局如下图:

zlbytes: 32 位无符号整型,记录 ziplist 整个结构体的占用空间大小。当然了也包括 zlbytes 本身。这个结构有个很大的用处,就是当需要修改 ziplist 时候不需要遍历即可知道其本身的大小。 这个 SDS 中记录字符串的长度有相似之处,这些好的设计往往在平时的开发中可以采纳一下。
zltail: 32 位无符号整型, 记录整个 ziplist 中最后一个 entry 的偏移量。所以在尾部进行 POP 操作时候不需要先遍历一次。
zllen: 16 位无符号整型, 记录 entry 的数量, 所以只能表示 2^16。但是 Redis 作了特殊的处理:当实体数超过 2^16 ,该值被固定为 2^16 - 1。 所以这种时候要知道所有实体的数量就必须要遍历整个结构了。
entry: 真正存数据的结构。
zlend: 8 位无符号整型, 固定为 255 。为 ziplist 的结束标识。
entry 节点每个 entry 都包含两条信息的元数据为前缀。 第一元数据用来存储前一个 entry 的长度,以便能够从后向前遍历列表。 第二元数据是表示 entry 的编码形式。 用来表示 entry 类型,整数或字符串,在字符串的情况下,它还表示字符串有效的长度。
所以一个完整的 ziplist 是这样存储的:

记录前一个 entry 的长度。若前一个 entry 的长度小于 254 , 则使用 1 个字节的 8 位无符号整数来表示。
若前一个 entry 长度大于等于 254,则使用 5 个字节来表示。第 1 个字节固定为 254 (FE) 作为标识,剩余 4 字节则用来表示前一个 entry 的实际大小。
所以两种情况下的 entry 结构如下所示:
1. 前一个 entry 大小不超过 253。<prevlen from 0 to 253> <encoding> <entry>2. 前一个 entry 大小超过 253。0xFE <4 bytes unsigned little endian prevlen> <encoding> <entry>encoding 编码entry 的编码字段取决于具体值的内容,分为字符串、数字两种类型单独处理。
一、当 entry 是字符串时,有 3 种编码方式。编码第 1 个字节的前 2 位将保存用于存储字符串长度的编码类型,后面是字符串的实际长度。
1. 长度小于或等于 63 字节(6 位)的字符串值。 “pppppp”表示无符号的 6 位数据长度。|00pppppp| - 1 byte2. 长度小于或等于 16383 字节(14 位)的字符串值。14 位的数据采用 big endian 存储。big endian 是一种字节序方式,有Little-Endian、Big-Endian两种。|01pppppp|qqqqqqqq| - 2 bytes3. 长度大于或等于 16384 字节的字符串值。采用 big endian 存储且可表示的字符串长度最大2^32-1,所以第一个字节没有用到,所以低6位没有用,所以都是0。|10000000|qqqqqqqq|rrrrrrrr|ssssssss|tttttttt| - 5 bytes 二、当 entry 是整数时,有 6 种编码方式。前 2 位都固定为 1,接下来的 2 位用于指定将在此标头后存储哪种类型的整数。
与 ziplist 标头一样,所有整数都以 Little-Endian 序表示,即使此代码是在 Big-Endian 系统中编译的。
1. 整数编码为 int16_t(2 字节)。|11000000| - 3 bytes2. 整数编码为int32_t(4个字节)。|11010000| - 5 bytes3. 整数编码为 int64_t(8 字节)。|11100000| - 9 bytes4. 整数编码为24位带符号(3个字节)。|11110000| - 4 bytes5. 整数编码为 8 位有符号(1 字节)。|11111110| - 2 bytes6. 0到12的无符号整数。编码后的值实际上是1到13,因为0000和1111不能用,所以要从编码后的4位值中减去1才能得到正确的值。|1111xxxx| - (with xxxx between 0001 and 1101) immediate 4 bit integer三、结尾编码标识
1. 表示 ziplist 结尾的标识。|11111111|总结ziplist 为了节省内存,采用了紧凑的连续存储。所以在修改操作下并不能像一般的链表那么容易,需要从新分配新的内存,然后复制到新的空间。
ziplist 是一个双向链表,可以在时间复杂度为O(1)从下头部、尾部进行pop或push。
可能会出现连锁更新现象。
其实使用中并没有直接操作这种数据结构,但是可以设置何种情况下使用它。可以在 Redis 的配置文件中进行设置。
如有以下可选设置项:
hash-max-ziplist-entries:hash 类型元素数量超过指定数据后时候。使用 hash 存储, 否则使用压缩表。
hash-max-ziplist-value: hash 类型元素长度超过指定数据后时候。 使用 hash 存储,否则使用压缩链表。
zset-max-ziplist-entries:zset 类型 压缩列表 ziplist 最大限制元素数。超过指定值将会使用跳表 skiplist + dict 来存储。
zset-max-ziplist-value:set 类型 压缩列表 ziplist 最大限制大小。超过指定将会使用跳表 skiplist+dict 来存储。
到此这篇关于Redis ziplist 压缩列表的源码解析的文章就介绍到这了,更多相关Redis ziplist 压缩列表内容请搜索软件开发网以前的文章或继续浏览下面的相关文章希望大家以后多多支持软件开发网!
边栏推荐
- 英语没学好到底能不能做coder,别再纠结了先学起来
- 事件队列、微任务与宏任务的理解和面试题
- QQmlApplicationEngine failed to load component qrc:/main.qml:-1 No such file or directory
- SM2246EN+闪迪15131
- Code shoe set - mt3435 · assignment - bipartite graph problem - Graphic explanation
- 数据智能——DTCC2022!中国数据库技术大会即将开幕
- 如何做好测试用例设计
- [jetsonnano] [tutorial] [introductory series] [i] how to enable VNC sharing
- Convert seconds to * * hours * * minutes
- matlab Delaunay 三角剖分内的查询点
猜你喜欢

Promise from recognition to use

项目配置了eslint,编辑器没有关闭eslint功能的情况下,eslint没有生效

台湾SSS鑫创SSS1700替代Cmedia CM6533 24bit 96KHZ USB音频编解码芯片

Idle fish is hard to turn over

线下门店为什么要做新零售?

Inventory the six second level capabilities of Huawei cloud gaussdb (for redis)

VR云展厅如何给线下实体带来活力?有哪些功能?

标配10个安全气囊,奇瑞艾瑞泽8安全防护无死角

实现各种效果和功能的按钮,读这篇文章就够了

VR全景中特效是如何编辑的?细节功能如何展示?
随机推荐
Abaqus 2022软件安装包和安装教程
今早,投资人开始集体出差
c语言数组截取,C# 字符串按数组截取方法(C/S)
哪个券商佣金的佣金最低?另外,手机开户安全么?
标配10个安全气囊,奇瑞艾瑞泽8安全防护无死角
2022年高考都结束了,还有人真觉得程序员下班后不需要学习吗?
网易云签到可抽奖?那一年我能签到365天。不信?你看。
达梦数据库重新初始化实例操作记录
Growth summer challenge is coming, exclusive community welfare is coming ~ get CSDN customized T-shirt for free
Advanced skills of testers: a guide to the application of unit test reports
QQmlApplicationEngine failed to load component qrc:/main.qml:-1 No such file or directory
Final chapter of binary tree
英语没学好到底能不能做coder,别再纠结了先学起来
2022 最新 JCR正式发布全球最新影响因子名单(前600名)
Connect to lab server
SQL continuous login problem
This morning, investors began to travel collectively
Alibaba Tianchi SQL training camp learning notes 5
企业中台规划和IT架构微服务转型
MQ selection (2022.5.9-5.15)