Redis数据结构(二)跳表、整数集合、压缩列表

本文详细介绍了Redis中跳表(Ziplist)的结构与工作原理,包括节点组成、层级随机生成和遍历机制。同时,提到了整数集合(Intset)的数据结构和升级过程,以及压缩列表(Ziplist)的存储方式和节点属性。这些数据结构优化了内存使用,提高了数据操作效率。
摘要由CSDN通过智能技术生成

Skip List

跳表是一种有序数据结构,Redis使用跳表作为有序集合键的底层实现之一。
redis6.0的代码中,跳表结构由server.h中定义,其中zskiplistNode表示跳表节点,zskiplist保存跳表节点相关信息,比如节点数量,以及指向表头电点和表尾节点的指针等。
在这里插入图片描述
上图左侧是zskiplist结构。其中header、tail表示头尾节点。level记录目前表内,层数最大的节点层数(不计算头结点)。length记录跳表长度,表示目前包含节点的数量(不计算头结点)。

跳表节点

typedef struct zskiplistNode {
    sds ele;
    double score;
    struct zskiplistNode *backward;
    struct zskiplistLevel {
        struct zskiplistNode *forward;
        unsigned long span;
    } level[];
} zskiplistNode;
  • ele,字符串对象

  • score,分值,跳表中节点按照score从小到大排序。同一跳表中,节点保存对象必须唯一,但分值可相同,分值相同的节点按照ele排序。如上图中o1 <= o2 <= o3.
    在这里插入图片描述

  • backward,后退指针。用于从表尾访问节点,每次可后退一个节点。图5-6中虚线表示从表尾向表头遍历节点。首先通过tail访问表尾节点。然后通过BW访问前一个节点,直至BW为NULL。

  • level。跳表节点的level数组可以包含多个元素,每个元素都包含一个指向其他节点的指针。每次创建一个新跳表节点时,程序会根据幂次定律(越大的数出现的概率越小)随机生成[1,32]之间的值作为level数组大小,这个大小就是层的“高度”。
    在这里插入图片描述

  • forward,前进指针。每层都有一个指向表尾的前进指针,用于从表头向表尾访问。图5-3虚线表示表头向表尾方向遍历节点的路径。

    • 1)迭代程序首先访问跳表的第一个节点(表头),然后从第四层前进指针移动到表的第二个节点。
    • 2)在第二个节点时,程序沿第二层前进指针移动到表的第三个节点。
    • 3)在第三个节点时,程序按第二层移动到第四个节点。
    • 4)继续按照前进指针移动时,为NULL,此次遍历结束。
      在这里插入图片描述
  • span,跨度。记录两个节点间的距离。两个节点间跨度越大,距离越远。指向NULL的所有前进指针跨度为0。跨度是用来计算排位(rank)的:在查找某个节点的过程中,将沿途访问过的所有层的跨度累积起来,得到的结构就是目标节点再跳表中的rank。例如图5-4查找score为3,对象为o3的节点时,沿途经历的层:查找经过一个层,并且跨度为3,所以目标节点再跳表中的rank为3。

跳表

实现如下:

typedef struct zskiplist {
    struct zskiplistNode *header, *tail;
    unsigned long length;
    int level;
} zskiplist;

跳表API也在server.h中,包含创建释放跳表、插入删除新节点、获取节点rank等。

整数集合

整数集合(intset)是集合键的底层实现之一,当一个集合只包含整数元素,并且元素数量不多时,就会采用整数集合作为底层实现。

整数集合的实现

typedef struct intset {
    uint32_t encoding; // 编码方式
    uint32_t length;	// 包含元素数量
    int8_t contents[];	//元素数组
} intset;

content数组中的数据项从小到大有序排列。encoding标识该intset的元素是int8、int32还是int64。

升级

每当将新元素插入整数集合,并且新元素类型比当前所有元素类型要长时,整数集合先进行升级,再将新元素插入。
升级并添加元素分三步:

  1. 根据新元素类型,扩展整数集合底层数组的空间大小,并为新元素分配空间。
  2. 将底层数组的所有元素转换成与新元素相同类型,并放置到正确的位上(维持大小顺序)。
  3. 插入新元素。
    在这里插入图片描述

压缩列表

压缩列表(ziplist)是列表键和哈希键的底层实现之一,当一个列表键只包含少量列表项(或哈希键只包含少量kv对),并且每个列表项要么是小整数值,要么是长度较短字符串,那么Redis会使用ziplist作为底层实现。

压缩列表的构成

压缩列表是由一系列特殊编码的连续内存块组成的顺序型数据结构,一个压缩列表可以包含任意多个节点,每个节点可以保存一个字节数组或一个整数值。
图7-1展示压缩列表的各个组成部分。
在这里插入图片描述
各个字段的说明如下:
在这里插入图片描述
在这里插入图片描述

压缩列表节点的构成

在这里插入图片描述

previous_entry_length属性以字节为单位,记录压缩列表的前一个节点长度。previous_entry_length属性的长度可以是1字节或5字节。通过previous_entry_length,程序可以根据当前节点起始地址计算前一个节点起始地址。

encoding属性记录街爱你的content属性所保存数据类型和长度。

content保存节点值,可为整数或字节数组。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值