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

这篇具有很好参考价值的文章主要介绍了Redis从入门到精通【高阶篇】之底层数据结构压缩列表(ZipList)详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


Redis从入门到精通【高阶篇】之底层数据结构压缩列表(ZipList)详解
前面的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
    Redis从入门到精通【高阶篇】之底层数据结构压缩列表(ZipList)详解

其中,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文章来源地址https://www.toymoban.com/news/detail-474774.html

到了这里,关于Redis从入门到精通【高阶篇】之底层数据结构压缩列表(ZipList)详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Redis - 底层数据结构

    Redis 的底层数据结构主要以下几种: SDS(Simple Dynamic String, 简单动态字符串) ZipList(压缩列表) QuickList(快表) Dict(字典) IntSet(整数集合) ZSkipList(跳跃表) 在 Redis 中,并不会直接使用 C 语言自带的字符串结构作为实际的存储结构,而只是将字符串作为字面量使用,大多数情况使用自

    2023年04月12日
    浏览(44)
  • Redis五种数据结构底层编码结构

    Redis中的 任意数据类型的键和值都会被封装为一个RedisObject ,也叫做Redis对象,源码如下: 对象头不包含数据就已经占16字节,如果数据存string型,一个string一个对象头比较浪费空间,存大量数据时还是建议使用集合,这样可以共用一个对象头更加节省空间 Redis中会根据存储

    2024年02月11日
    浏览(41)
  • redis 底层数据结构详解

    目录   1.字符串 1.1 SDS定义 1.2 SDS1好处 2.列表 2.1 void 实现多态 3 字典 3.1   底层实现是hash表 3.2 字典结构 3.3 哈希算法 3.3.1 rehash 3.3.2 rehash的触发时机 3.3.3 渐进式rehash 扩展或收缩哈希表需要将ht[0]里面的所有键值对rehash到ht[1]里面,但是,这个rehash动作并不是一次性、集中式

    2023年04月09日
    浏览(48)
  • Redis - 数据类型映射底层结构

    从数据类型上体现就是,同一个数据类型,在不同的情况下会使用不同的编码类型,底层所使用的的数据结构也不相同。 字符串对象的编码可以是 int 、 raw 和 embstr 三者之一。 embstr 编码是专门用于保存简短字符串的一种优化编码方式,与 raw 编码会调用两次内存分配函数分

    2023年04月21日
    浏览(38)
  • redis的hash数据结构底层简记

    hash:k和v都是string的hash表。 HSET(设置集合数据,4.0之前只能设置1个,之后可以设置多个),HSETNX(若k不存在则设置对应v),HDEL(删除指定kv,可以一次删除多个),DEL(删除Hash对象),HMSET(设置多个kv,4.0之后废弃),HGETALL(查找全部数据),HGET(查询k对应的v),HLEN(查

    2024年02月21日
    浏览(37)
  • 【redis】redis的5种数据结构及其底层实现原理

    Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(无序集合)及zset(有序集合)。 在秒杀项目里,我用过redis的Set和Hash结构: String:一个 key 对应一个字符串,string是Redis 最基本的数据类型。(字节的abase框架只实现了redis的string数据结构,导致我们如

    2024年02月09日
    浏览(75)
  • 【从零开始学习Redis | 第八篇】认识Redis底层数据结构(下)

    目录 前言:   ZipList: Ziplist的特性: QucikList: QuicList特征: SkipList: 跳表特征: RedisObijct:  小心得: 总结:           在现代软件开发中,数据存储和处理是至关重要的一环。为了高效地管理数据,并实现快速的读写操作,各种数据库技术应运而生。其中,Redis作为一种

    2024年04月12日
    浏览(55)
  • Redis追本溯源(二)数据结构:String、List、Hash、Set、Zset底层数据结构原理

    Redis 并没有直接用 C 语言的字符串,而是自己搞了一个 sds 的结构体来表示字符串,这个 sds 的全称是 Simple Dynamic String,翻译过来就是“简单的动态字符串”。 安全的二进制存储 资源。关于sds的扩容和缩容下面会进行详细的介绍,这里先不赘述了。 在一些情况中,我们需要

    2024年02月16日
    浏览(55)
  • 【C++入门】STL容器--vector底层数据结构剖析

    目录  前言  1. vector的使用       vector的构造  vector迭代器  vector空间相关的接口  vector 功能型接口  find  swap  insert  erase 2. vector内部数据结构剖析 reserve  push_back和pop_back size、capacity、empty、operator[ ];  insert和erase resize swap  拷贝构造和赋值重载 构造函数补充  迭代器

    2024年01月25日
    浏览(57)
  • 数据结构从入门到精通——栈

    栈,作为一种后进先出(LIFO)的数据结构,在计算机科学中扮演着重要的角色。它的特性使得它在处理函数调用、括号匹配、表达式求值等问题时具有得天独厚的优势。然而,如果我们跳出传统思维的束缚,会发现栈的用途远不止于此。 在现代软件开发中,栈的概念被广泛

    2024年03月11日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包