Redis

关注公众号 jb51net

关闭
首页 > 数据库 > Redis > Redis中跳表的实现原理

Redis中跳表的实现原理分析

作者:空说

Redis中的跳表是一种高效的多层链表结构,通过随机概率算法决定节点的层数,从而实现快速的插入、删除和查询操作,跳表的平均时间复杂度为O(logn),最差情况为O(n),每个节点包含值和指向更高层节点的指针,以及回退指针以提高操作效率

Redis中跳表的实现原理

跳表: 主要通过多重链表实现,最底层包含所有元素,上层都是底层元素的跳跃索引,每一层的元素是从下一层中随机选择的,通常使用概率算法来决定一个元素是否出现在上一层。

每个节点包含一个值和指向下一层节点的指针

原理

跳表,一句话概括:就是一个多层索引的链表,每一层索引的元素在最底层的链表中可以找到( 这一点和 B+树是一样的 )

如下图所示:

这就是一个简单的跳表实现了,每个颜色代表一层,绿色的就是链表的最底层了

接下来我们通过查询和添加元素来了解其功能流程:

1) 查询元素: 这里我们与传统的链表进行对比,来了解跳表查询的高效。

2) 插入元素: 我们插入一条 score 为 48 的数据

补充插入的随机层级

具体解释

跳表在创建节点时候,会生成范围为[0-1]的一个随机数,如果这个随机数小于 0.25,那么层数就增加 1 层,然后继续生成下一个随机数,这样的做法,相当于每增加一层的概率不超过 25%,层数越高,概率越低,层高最大限制是 64。(创建跳表时头结点就等于层高)

//5层跳表
10
10        50
10  20    50
10  20 30 50
10  20 30 50
//比如插入20这个结点时会生成随机数
    如果>0.25,那么这一层的高度+1,然后继续生成随机数
    								如果还是>0.25,高度继续+1,依次类推
    如果<0.25,终止,记录 该结点的最终高度

定位层级后,再将每一层的链表节点进行补齐,就是在 40 与 50 之间插入一个新的链表节点48,插入过程与链表插入是一样的。

redis的跳表

就是在此基础上添加回退指针,且score能重复

为什么 Redis 跳表实现多了个回退指针(前驱指针)?

回退指针主要是为了提高跳表的操作效率和灵活性,例如在进行删除操作时,需要找到要删除节点的前驱节点以便更新指针。回退指针使得这一过程更为高效,避免了从最高层开始逐层查找。

尤其是在频繁插入和删除的场景中,回退指针减少了节点之间指针的更新复杂度,提升性能。

typedef struct zskiplistNode {
    //Zset 对象的元素值
    sds ele;
    //元素权重值
    double score;
    //后退指针
    struct zskiplistNode *backward;
  
    //节点的level数组,保存每层上的前向指针和跨度
    struct zskiplistLevel {
        struct zskiplistNode *forward;
        unsigned long span;
    } level[];
} zskiplistNode;

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文