Redis数据结构之跳跃表使用学习

 更新时间:2023年07月03日 17:25:48   作者:Hunter  
这篇文章主要为大家介绍了Redis数据结构之跳跃表使用学习,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

Redis跳跃表结构

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

当有序集合包含的元素数量较多,又或者有序集合中的元素的成员是比较长的字符串时,Redis 就会使用跳跃表来作为有序集合的底层实现。

以下是本篇笔记目录:

  • 跳跃表及跳跃表节点结构
  • 跳跃表属性
  • 跳跃表节点属性
  • 跳跃表节点层(level)的生成
  • 跳跃表的查询过程

1、跳跃表及跳跃表节点结构

接下来介绍一下跳跃表和跳跃表节点结构。

跳跃表结构:

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

跳跃表结构中包含指向表头和表尾的指针,以及 length 字段表示表中节点的数量,level 字段则是表示所有跳跃表节点中最大的节点层数,层数的概念在跳跃表节点结构中再详细说明。

跳跃表节点结构:

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

我们可以将跳跃表理解成链表,不过链表上的每个节点都有指向前面一个节点的指针和多个指向后面某些节点的指针,指向后面的指针以数组的形式存在。

接下来我们以一张图来示意一下跳跃表及其节点之间的关系。

2、跳跃表结构

在上面的伪代码示例和上图结构中,可以看到一个跳跃表结构如下几个属性:

a) header

header 是跳跃表的头节点指针,可以快速定位跳跃表的头节点

b) tail

tail 是跳跃表的尾部节点指针,可以快速定位跳跃表的尾部节点

c) level

level 表示的是跳跃表节点中层数最高的数值,比如在图中第三个跳跃表节点的层数最高,数值是 5,所以跳跃表的这个值是 5。

d) length

length 属性表示的是跳跃表节点的个数,也就是跳跃表的长度。

3、跳跃表节点结构

跳跃表节点的各个属性如下:

a) obj

节点的成员对象,见图中的,o1,o2,o3,是一个指针,指向一个字符串对象,字符串对象保存着一个 SDS 值,就是有序集合中存储的数值。

b) score

有序集合用来进行排序的分值,有序集合通过这个属性用来对集合的元素进行排序,保存的是 double 类型的浮点数,在跳跃表中,所有节点按照分值从小到大来排序。

c) backward

后退指针,跳跃表的每个节点通过这个属性指向前一个节点,用于从表尾向表头方向访问节点。

图中展示了如何从表尾向跳跃表的头节点遍历的过程:通过 tail 指针指向跳跃表的尾部节点,然后通过 backward 后退指针逐个往前遍历,直到第一个节点的 backward 为 NULL 表示遍历结束。

d) skiplistLevel

skiplistLevel 是跳跃表节点的层,层数介于 1 到 32 之间,每个层的都包含两个属性,前进指针和跨度。

前进指针:forward,指向同一层级的下一个跳跃表节点

跨度:span,用于记录到同层级的下一个节点之间的距离,比如第一个节点的第四层级,下一个节点的第四层级是第三个节点,因此,o1 的第四层级的的跨度是 2。

4、跳跃表节点层(level)介绍

前面介绍跳跃表节点的层属性是一个数组,包含多个指向下一个同一层级的指针,而每个节点层的大小则是根据幂次定律(power law) 来生成的。

在创建一个跳跃表节点的时候,程序都会根据幂次定律随机生成一个介于 1 到 32 之间的值作为 level 数组的大小,这个规则是越大的数出现的概率越小,它有一种计算方式,层数每加 1,出现的概率都是前一个数字的 0.25。

比如 level = 1 的概率是 0.75,那么 level = 2 的概率是 0.75 0.25,level = 3 的概率则是 0.75 0.25 * 0.25,直到最高层数

所以每个跳跃表节点的层数都是随机的,跟这个节点在跳跃表的前后位置无关。

5、跳跃表的查询过程

以上面的图为例,比如我们想查询 score 为 2.0 的 o2 节点,那么查询的过程是这样的:

  • 首先根据头节点的最高一层节点,在图中是 L5,L5 指向的是 o3 节点,o3 节点的分值比目标分值 2.0 大,舍弃
  • 头节点往下降一层,到 L4,L4 指向下个节点 o1,o1的 score 比 2.0 小,跳到 o1 节点,继续查询
  • o1 节点的 L4 指向的下一节点是 o3,o3 的 score 比 2.0 大,舍弃,o1 的 L4 继续下降一层
  • o1 节点的 L3 节点指向的 o3 还是不符合条件,继续下降一层
  • o1 节点的 L2 节点指向的 o2 节点,其分值满足条件,而从 o1 到 o2 的跨度为 1 + 1 = 2

以上就是Redis数据结构之跳跃表使用学习的详细内容,更多关于Redis数据结构跳跃表的资料请关注脚本之家其它相关文章!

相关文章

  • Redis中key的操作命令

    Redis中key的操作命令

    本文主要介绍了Redis中key的操作命令,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-06-06
  • redis使用不当导致应用卡死bug的过程解析

    redis使用不当导致应用卡死bug的过程解析

    本文主要记一次找因redis使用不当导致应用卡死bug的过程,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2021-07-07
  • Redis String 类型和 Hash 类型学习笔记与总结

    Redis String 类型和 Hash 类型学习笔记与总结

    这篇文章主要介绍了Redis String 类型和 Hash 类型学习笔记与总结,本文分别对String 类型的一些方法和Hash 类型做了详细介绍,需要的朋友可以参考下
    2015-06-06
  • Redis全量同步和增量同步原理

    Redis全量同步和增量同步原理

    主从第一次同步是全量同步:也就是说,当你主从节点连接建立后,需要执行一次全量同步,但如果slave重启后同步,此时slave重启后,slave节点和master节点的数据之间有落后,因此需要进行增量同步,感兴趣的同学可以参考阅读
    2023-04-04
  • 解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)

    解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)

    该文章介绍了使用Redis的阻塞队列和Stream流的消息队列来优化秒杀系统的方案,通过将秒杀流程拆分为两条流水线,使用Redis缓存缓解数据库压力,并结合Lua脚本进行原子性判断,使用阻塞队列和消息队列异步处理订单,有效提高了系统的并发处理能力和可用性
    2025-02-02
  • Redis哨兵机制的使用详解

    Redis哨兵机制的使用详解

    文章讲解了Redis哨兵机制的基本原理、主库和从库自动切换的过程、如何减少误判、哨兵集群的组成和通信机制,以及哨兵在故障发生时如何选举Leader进行主从切换
    2025-01-01
  • redis数据结构之intset的实例详解

    redis数据结构之intset的实例详解

    这篇文章主要介绍了redis数据结构之intset的实例详解的相关资料, intset也即整数集合,当集合保存的值数量不多时,redis使用intset作为其底层数据保存结构,希望通过本文能帮助到大家,需要的朋友可以参考下
    2017-09-09
  • redis setIfAbsent返回null的问题及解决

    redis setIfAbsent返回null的问题及解决

    这篇文章主要介绍了redis setIfAbsent返回null的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • Redis 安装 redistimeseries.so(时间序列数据类型)的配置步骤

    Redis 安装 redistimeseries.so(时间序列数据类型)的配置步骤

    这篇文章主要介绍了Redis 安装 redistimeseries.so(时间序列数据类型)详细教程,配置步骤需要先下载redistimeseries.so 文件,文中介绍了启动失败问题排查,需要的朋友可以参考下
    2024-01-01
  • redis集群实现清理前缀相同的key

    redis集群实现清理前缀相同的key

    这篇文章主要介绍了redis集群实现清理前缀相同的key,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10

最新评论