Redis学习(二)-- Redis跳表

Redis跳表(跳跃表)简介

Redis跳表是有序集合zset的底层实现基础,其主要思想对有序链表的部分节点分层,每一层都是有序链表,越上层两个节点之间的跨度越大,查询时从最上层开始,先找一个大致的范围,再向下层,找到更精确的范围,直到找到某个值。(啊如果没看过跳表结构的可能不好理解,没关系,看完以下介绍再回来细品)

Redis跳表结构

Redis跳表基本思想

Redis跳表本质是一个分层的有序链表,其结构的大致示意图如下:

在这里插入图片描述

底层是原始的有序链表,此时我们查找的时间复杂度为O(N)。

上图的分层结构:

​ 第1层:在第0层上,每2个节点提取一个节点构成第1层的有序链表(这也表示:上层节点一定在下层节点中)

​ 第2层:在第1层上,提取了1个节点

采用分层链表,查找时间复杂度降为O(logN)。以查找31为例,查找的流程为:

  1. 从第2层开始,31节点比21节点大,21节点的next又指向null,从21节点向下
  2. 31节点>21节点,31节点<41节点,因此从21节点向下
  3. 向后查找,找到31节点

综上,通过将有序链表的部分节点进行分层,从上层开始一次向后查找,如果本层节点的下一节点大于查找结点或者为NULL,从当前节点向下层向后查找,直到找到。再数量比较大时,可以跳过很多节点,降低时间复杂度。

Redis跳表结构

在上述基本思想的基础上,Redis跳表还加入了一些辅助的节点信息,如下图所示:
在这里插入图片描述

跳跃表结构体

跳跃表结构体用来管理节点、存储跳表的信息,其主要包括:

  • header:指向头节点(zskiplistNode类型)
  • tail:指向尾部节点
  • length:跳表的长度(除头节点外的节点总数)
  • level:跳表的高度

源码中,跳表结构体使用zskiplist实现:

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

通过跳表结构体的属性,可以在O(1)时间复杂度下,获取头节点、尾节点、长度、高度。

跳跃表节点
typedef struct zskiplistNode{
    sds ele;            //sds类型member值
    double score;       //分值
    struct zskiplistNode *backward; //后退指针,指向当前节点最底层的前一个节点
    struct zskiplistLevel{
        struct zskiplistNode *forward; //本层的下一个节点
        unsigned int span;             //本层每个节点和下一个节点(forward)之间的元素个数
    }level[]; //柔性数组,level[i]代表跳表的第i层,每个节点有几层是在生成节点时使用算法得到的
}zskiplistNode;
头节点

头节点是一个特殊的跳表节点,它的level数组个数为固定值64(最大值),头节点中不存储member和score值(NULL和0),不计入总长度。初始化时,64层的forward指向NULL,span=0

Redis跳表的基本操作

创建跳表

  1. 创建跳表结构体对象zsl
  2. 创建头节点,并将zsl header指向这个头节点
  3. zsl的level初始化为1,长度初始化为0,尾节点指向NULL

插入节点

删除节点

持续更新中
Redis跳表是面试常客哦~

本文参考《Redis5 设计与源码分析》

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值