|NO.Z.00060|——————————|BigDataEnd|——|Hadoop&Redis.V05|——|Redis.v05|RedisDB结构.v05|结构7种type.v03|

一、压缩列表
### --- 压缩列表

~~~     压缩列表(ziplist)是由一系列特殊编码的连续内存块组成的顺序型数据结构
### --- 节省内存

~~~     是一个字节数组,可以包含多个节点(entry)。每个节点可以保存一个字节数组或一个整数。
### --- 压缩列表的数据结构如下:

~~~     zlbytes:压缩列表的字节长度
~~~     zltail:压缩列表尾元素相对于压缩列表起始地址的偏移量
~~~     zllen:压缩列表的元素个数
~~~     entry1..entryX : 压缩列表的各个节点
~~~     zlend:压缩列表的结尾,占一个字节,恒为0xFF(255)

### --- entryX元素的编码结构:

~~~     previous_entry_length:前一个元素的字节长度
~~~     encoding:表示当前元素的编码
~~~     content:数据内容

### --- ziplist结构体如下:

typedef struct zlentry {
    unsigned int prevrawlensize;                                        //previous_entry_length字段的长度
    unsigned int prevrawlen;                                            //previous_entry_length字段存储的内容
    unsigned int lensize;                                               //encoding字段的长度
    unsigned int len;                                                   //数据内容长度
    unsigned int headersize;                                            //当前元素的首部长度,即previous_entry_length字段长度与 encoding字段长度之和。
    unsigned char encoding;                                             //数据类型
    unsigned char *p;                                                   //当前元素首地址
} zlentry;
### --- 应用场景:

~~~     sorted-sethash元素个数少且是小整数或短字符串(直接使用)
~~~     list用快速链表(quicklist)数据结构存储,而快速链表是双向列表与压缩列表的组合。(间接使用)
二、整数集合
### --- 整数集合

~~~     整数集合(intset)是一个有序的(整数升序)、存储整数的连续存储结构。
~~~     当Redis集合类型的元素都是整数并且都处在64位有符号整数范围内(2^64),使用该结构体存储。
127.0.0.1:6379> sadd set:001 1 3 5 6 2
(integer) 5
127.0.0.1:6379> object encoding set:001
"intset"
127.0.0.1:6379> sadd set:004 1 100000000000000000000000000 9999999999
(integer) 3
127.0.0.1:6379> object encoding set:004
"hashtable"
### --- intset的结构图如下:

typedef struct intset{
    //编码方式
    uint32_t encoding;
    //集合包含的元素数量
    uint32_t length;
    //保存元素的数组
    int8_t contents[];
}intset;
### --- 应用场景:

~~~     可以保存类型为int16_tint32_t 或者int64_t 的整数值,并且保证集合中不会出现重复元素。
三、快速列表(重要)
### --- 快速列表(重要)
### --- 双向列表(adlist)

~~~     快速列表(quicklist)是Redis底层重要的数据结构。是列表的底层实现。
~~~     (在Redis3.2之前,Redis采用双向链表(adlist)和压缩列表(ziplist)实现。)
~~~     在Redis3.2以后结合adlist和ziplist的优势Redis设计出了quicklist。
### --- 双向链表优势:

~~~     1. 双向:链表具有前置节点和后置节点的引用,获取这两个节点时间复杂度都为O(1)。
~~~     2. 普通链表(单链表):节点类保留下一节点的引用。
~~~     链表类只保留头节点的引用只能从头节点插入删除
~~~     3. 无环:表头节点的 prev 指针和表尾节点的 next 指针都指向 NULL,
~~~     对链表的访问都是以 NULL 结束。环状:头的前一个节点指向尾节点
~~~     4. 带链表长度计数器:通过 len 属性获取链表长度的时间复杂度为 O(1)。
~~~     5. 多态:链表节点使用 void* 指针来保存节点值,可以保存各种不同类型的值。
### --- 快速列表

~~~     quicklist是一个双向链表,链表中的每个节点时一个ziplist结构。
~~~     quicklist中的每个节点ziplist都能够存储多个数据元素。
### --- quicklist的结构定义如下:

typedef struct quicklist {
    quicklistNode *head;                                                // 指向quicklist的头部
    quicklistNode *tail;                                                // 指向quicklist的尾部
    unsigned long count;                                                // 列表中所有数据项的个数总和
    unsigned int len;                                                   // quicklist节点的个数,即ziplist的个数
    int fill : 16;                                                      // ziplist大小限定,由list-max-ziplist-size给定
    (Redis设定)
    unsigned int compress : 16;                                         // 节点压缩深度设置,由list-compress-depth给定(Redis设定)
} quicklist;
### --- quicklistNode的结构定义如下:

typedef struct quicklistNode {
    struct quicklistNode *prev;                                         // 指向上一个ziplist节点
    struct quicklistNode *next;                                         // 指向下一个ziplist节点
    unsigned char *zl;                                                  // 数据指针,如果没有被压缩,就指向ziplist结构,反之指向 quicklistLZF结构
    unsigned int sz;                                                    // 表示指向ziplist结构的总长度(内存占用长度)
    unsigned int count : 16;                                            // 表示ziplist中的数据项个数
    unsigned int encoding : 2;                                          // 编码方式,1--ziplist,2--quicklistLZF
    unsigned int container : 2;                                         // 预留字段,存放数据的方式,1--NONE,2--ziplist
    unsigned int recompress : 1;                                        // 解压标记,当查看一个被压缩的数据时,需要暂时解压,标记此参数为 1,之后再重新进行压缩
    unsigned int attempted_compress : 1;                                // 测试相关
    unsigned int extra : 10;                                            // 扩展字段,暂时没用
} quicklistNode;
### --- 数据压缩

~~~     # quicklist每个节点的实际数据存储结构为ziplist,
~~~     这种结构的优势在于节省存储空间。为了进一步降低ziplist的存储空间,
~~~     还可以对ziplist进行压缩。Redis采用的压缩算法是LZF。
~~~     其基本思想是:数据与前面重复的记录重复位置及长度,不重复的记录原始数据。

~~~     # 压缩过后的数据可以分成多个片段,
~~~     每个片段有两个部分:解释字段和数据字段。quicklistLZF的结构体如下:
typedef struct quicklistLZF {
    unsigned int sz;                                                    // LZF压缩后占用的字节数
    char compressed[];                                                  // 柔性数组,指向数据部分
} quicklistLZF;
### --- 应用场景

~~~     列表(List)的底层实现、发布与订阅、慢查询、监视器等功能。

 
 
 
 
 
 
 
 
 

Walter Savage Landor:strove with none,for none was worth my strife.Nature I loved and, next to Nature, Art:I warm'd both hands before the fire of life.It sinks, and I am ready to depart
                                                                                                                                                   ——W.S.Landor

 

 

posted on   yanqi_vip  阅读(22)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示