Redis 源码解析 - 跳跃表(skiplist)

Redis 中的跳跃表(SkipList)是一种用于实现有序集合(Sorted Set)的数据结构,它提供了一个可以高效进行插入、删除、查找等操作的有序序列。跳跃表的设计基于概率平衡树的概念,但实现更为简洁且在实践中表现出优秀的性能。以下是 Redis 中跳跃表(SkipList)的主要组件及其源码解析要点:

跳跃表结构体定义

Redis 中跳跃表结构体主要包含两个部分:节点(zskiplistNode)和整体跳跃表(zskiplist)。

zskiplistNode 节点结构体
typedef struct zskiplistNode {
    // 成员对象
    robj *obj;
    // 分值
    double score;
    // 层次数组,每一层包含一个前后指针
    struct zskiplistLevel {
        // 指向下一层节点的指针
        struct zskiplistNode *forward;
        //跨度,用于估算此层的节点数量
        unsigned int span;
    } level[];
} zskiplistNode;

每个节点除了包含它所储存的成员对象(键值对中的值)和对应的分值外,还有一个可变大小的层次数组 level[],每个层级都有一个指向同一层级下一个节点的指针。

zskiplist 跳跃表结构体
typedef struct zskiplist {
    // 表头节点和表尾节点
    struct zskiplistNode *header, *tail;
    // 表中节点的数量
    unsigned long length;
    // 最大层级数
    int level;
    // 随机等级生成器的基数
    unsigned long long max_level;
    // 层级比例因子
    double p;
} zskiplist;

跳跃表包含表头节点、表尾节点、节点总数、当前最大层级数、随机等级生成器基数和层级概率比例因子。层级数是由一个随机函数决定的,这样可以让查找路径呈现近似于log N的分布。

跳跃表特性与操作

  1. 插入节点

    • 插入新节点时,先生成一个随机层数,然后将节点按照分值顺序插入到各个层级中。
    • 新节点会在每层找到合适的插入位置,并链接到合适的位置。
  2. 查找节点

    • 查找操作从最高层级开始,逐层向下比对分值,直到找到目标节点或到达最低层级。
  3. 删除节点

    • 删除节点时,需在所有层级中找到并断开相应的指针连接。
  4. 更新节点

    • 如果仅更改节点的分值导致排序变化,也需要更新相关指针关系。
  5. 渐进式复杂度

    • 跳跃表的查找、插入、删除操作平均时间复杂度为 O(log N),最坏情况下为 O(N)。

随机性与平衡性

Redis 跳跃表通过随机决定节点的高度来保持数据的均衡分布,高度较高的节点是稀疏的,而较低层级则较为稠密,这种设计使得大部分查找可以在较少的层级内完成,从而提高性能。

源码分析要点

在 Redis 源码中,有关跳跃表的实现包括了各种操作的实现函数,如 zslInsert()(插入)、zslDelete()(删除)、zslUpdateScore()(更新分值)等,这些函数均体现了跳跃表的上述特性,并利用了跳跃表节点的层级结构来高效执行相应操作。此外,还有用于初始化、释放跳跃表资源、遍历跳跃表等功能的辅助函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值