Redis 中跳表与实现

个人学习的总结学习笔记,参考资料都在文末给出,建议阅读
⭐️内容较多,点赞收藏不迷路 ⭐️


概述

是有序集合的底层实现之一。是一种有序数据结构,通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。

跳跃表是基于多指针有序链表实现的,可以看成多个有序链表。

在 Redis 中,跳跃表被用来实现有序集合健,另一个是在集群节点中用作内部数据结构。

在这里插入图片描述

在查找时,从上层指针开始查找,找到对应的区间之后再到下一层去查找。下图演示了查找 22 的过程。

在这里插入图片描述

实现

在这里插入图片描述

跳表由 redis.h/zskiplistNode 和 redis.h/zskiplist 两个结构定义。

zskiplist

上图最左边,用于保存跳跃表节点的相关信息。

typedef struct zskiplist {
    //表头结点和表尾结点
    struct zskiplistNode *header, *tail;
    //表中结点的数量
    unsigned long length;
    //表中层数最大的结点的层数
    int level;
}
  • header

    指向跳跃表的表头结点。

  • tail

    指向跳跃表的表尾结点。

  • level

    记录目前跳跃表内,层数最大的结点的层数,不包括表头结点。

  • length

    记录跳跃表目前包含结点的数量,不包含表头结点。

zskiplistNode

上图最右边的四个,用于表示跳表结点。多个跳表结点可以组成一个跳表。

typedef struct zskiplistNode {
    //层
    struct zskiplistLevel {
        //前进指针
        struct zskiplistNode *forward;
        //跨度
        unsigned int span;
    } level[];
    //后退指针
    struct zskiplistNode *backward;
    //分值
    double score;
    //成员对象
    robj *obj;
} zskiplistNode;
  • 层(level)

    L1表示第一层。层的数量越多,访问其他结点的速度就越快。

    随机生成介于 1~32 之间的值作为 level 数组的大小(高度)。

    • 前进指针

      用于访问位于表尾方向的其他结点。

    • 跨度

      记录前进指针所指向结点和当前结点的距离。

      用来计算排位(rank),将遍历的跨度相加即为目标结点的排位。

  • 后退指针(backward)

    BW标记,指向位于当前结点的前一个结点。

    从表尾向表头遍历时,程序首先通过跳表的 tail 指针访问表尾结点。

  • 分值(score)

    不唯一。

    上图中 1.0 2.0 3.0 即为结点分值,从小到大排列。

  • 成员对象(obj)

    唯一。

    o1 o2 o3 即为成员对象。

优点

与红黑树等平衡树相比,跳跃表具有以下优点:

  • 插入速度非常快速,因为不需要进行旋转等操作来维护平衡性;
  • 更容易实现;
  • 支持无锁操作。

拓展阅读

《Redis 五大数据类型》

《Redis 字典知多少?》


⭐️
如果对你有帮助,请点个赞,加个收藏噢!
参考资料

《Redis 设计与实现》
cyc2018

原创文章 51 获赞 1 访问量 3156

猜你喜欢

转载自blog.csdn.net/u014642412/article/details/106151113