Redis之跳跃表

跳跃表的介绍

跳跃表(SkipList)是一种有序的数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。

跳跃表支持平均O(logN)、最坏O(N)复杂度的节点查找,还可通过顺序性操作来批量处理节点。

跳跃表用在哪里?

Redis使用跳跃表作为有序集合键的底层实现之一,如果一个有序集合包含的元素比较多,或者元素的成员是比较长的字符串时,Redis使用跳跃表来作为有序集合键的底层实现。
除了有序集合键使用了跳跃表,另一个集群节点中用作内部数据结构

什么是有序集合(Sort Set)?

有序集合就是一个set集合,然后每个元素关联一个分数值。可以用它来实现微博的排名热榜,,

例如,fruit-price是一个有序集合键,保存了130款水果的价钱

redis>ZRANGE fruit-price 0 2 WITHSCORES
1)"banana"
2)"5"
3)"cherry"
4)"6.5"
...

fruit-price有序集合的所有数据保存在一个跳跃表里,每个跳跃表的节点(node)保存了一块水果的价钱信息,水果按价钱的高低从低到高在跳跃表里面排序。

跳跃表的实现

跳跃表由两个结构定义,zskiplistNode结构表示跳跃表的节点,zskiplist结构用于保存跳跃表节点的相关信息(节点数量,头尾指针)。

zskiplist结构包含的属性
header指向跳跃表的表头节点
tail指向跳跃表的表尾节点
level记录目前跳跃表内,层数最大的那个节点的层数(表头节点的层数不存在计算)
length记录跳跃表的长度,即跳跃表目前包含节点的数量(不计算头结点)
后退指针(backward)指向位于当前节点的前一个节点
分值(score)各节点保存分值大小 从小到大排列
成员对象每个节点保存的成员对象

层(level):节点中用L1、L2等标记节点各层。
每层都带两个属性:前进指针和跨度。
前进指针访问位于表尾的其他节点,跨度记录前进指针所指向节点和当前节点的距离。

跳跃表的节点

zskiplistNode

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

跳跃表层数越多,访问其他节点的速度就越快。
每次创建一个新跳跃表节点的时候,程序都根据幂次定律随机生成一个介于1和32之间的值作为level数组的大小,这个大小就是层的“高度”。
前进指针用于从表头向表尾方向访问节点。

遍历跳跃表:
寻找一个key。
首先从最高层开始,大于key(没找到),进入下一层,在这一层中,开始遍历,比key小,则向尾节点继续,当有比key大的,指针退后,并进入下一层,然后接着查找,知道找到key,或者到第一层也没找到对应的key。

跨度,也就相当于排名。

节点的分值是一个double类型的浮点数。
节点的成员对象是一个指针,它指向一个字符串对象,而字符串对象则保存着一个SDS值。
对象必须唯一,分值可以相同(按对象在字典序的大小排序)。

zskiplsit结构定义

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值