相关文章推荐
怕老婆的蟠桃  ·  求求你了,不要再自己实现这些逻辑了,开源工具 ...·  2 年前    · 
Code  ›  【愚公系列】2021年11月 C#版 数据结构与算法解析 Redis有序集合zset实现原理(跳表)开发者社区
redis 数据结构 链表
https://cloud.tencent.com/developer/article/1910541
苦闷的茴香
1 年前
愚公搬代码

【愚公系列】2021年11月 C#版 数据结构与算法解析 Redis有序集合zset实现原理(跳表)

前往小程序,Get 更优 阅读体验!
立即前往
腾讯云
开发者社区
文档 建议反馈 控制台
首页
学习
活动
专区
工具
TVP
最新优惠活动
文章/答案/技术大牛
发布
首页
学习
活动
专区
工具
TVP 最新优惠活动
返回腾讯云官网
愚公搬代码
首页
学习
活动
专区
工具
TVP 最新优惠活动
返回腾讯云官网
社区首页 > 专栏 > 【愚公系列】2021年11月 C#版 数据结构与算法解析 Redis有序集合zset实现原理(跳表)

【愚公系列】2021年11月 C#版 数据结构与算法解析 Redis有序集合zset实现原理(跳表)

作者头像
愚公搬代码
发布 于 2021-12-03 16:49:19
307 0
发布 于 2021-12-03 16:49:19
举报
文章被收录于专栏: 历史专栏

Redis有序集合中的元素的编码可以是 ziplist 或者 skiplist。ziplist和skiplist编码选择的标准在于Redis里的元素的数量以及元素成员的长度。当满足以下2个条件时,元素编码为ziplist:

  1. 有序集合保存的元素数量小于128个
  2. 有序集合保存的所有元素成员的长度小于64字节

ziplist:

ziplist编码的有序集合对象使用压缩列表作为底层实现。每个集合使用2个紧挨在一起的压缩列表节点来保存,第一个保存元素的成员,第二个保存元素的分值。压缩列表内的集合按分值从小到大排序,分值较小的元素被放置在靠近表头的位置,分值较大的元素在靠近表尾的位置。

skiplist:

跳跃表是一种有序的数据结构,它通过在每个节点上维持多个指向其它节点的指针来达到快速访问的目的。跳跃表在插入、删除和查找操作上的平均复杂度为O(logN),最坏为O(N),可以和红黑树相媲美,但是在实现起来,比红黑树简单很多。在Redis中的zset就是使用了跳跃表的实现有序集合。 具有如下性质:

  1. 由很多层结构组成;
  2. 每一层都是一个有序的链表,排列顺序为由高层到底层,都至少包含两个链表节点,分别是前面的head节点和后面的nil节点;
  3. 最底层的链表包含了所有的元素;
  4. 如果一个元素出现在某一层的链表中,那么在该层之下的链表也全都会出现(上一层的元素是当前层的元素的子集);
  5. 链表中的每个节点都包含两个指针,一个指向同一层的下一个链表节点,另一个指向下一层的同一个链表节点;
在这里插入图片描述
在这里插入图片描述

如上图所示,有一个链表保存着若干有序的数字,如果我们想找到 <16,23,25,31>这几个数字的话,简单的方法就是遍历一遍,时间复杂度为O(N)。数据量小的话还好,但是数据量一旦十分庞大的话就非常耗时了。这个时候就是需要我们去优化的了,找一个线性的顺序表,我们一般使用二分法查找,时间复杂度为O(LogN)。但是链表不适用二分法去查找(链表没有线性表那种连续下标,无法确定中间位置)。于是跳表产生了,它是一种随机化的数据结构,类似二叉搜索树,我们把一些节点提取出来作为索引。如下:>这几个数字的话,简单的方法就是遍历一遍,时间复杂度为O(N)。数据量小的话还好,但是数据量一旦十分庞大的话就非常耗时了。这个时候就是需要我们去优化的了,找一个线性的顺序表,我们一般使用二分法查找,时间复杂度为O(LogN)。但是链表不适用二分法去查找(链表没有线性表那种连续下标,无法确定中间位置)。于是跳表产生了,它是一种随机化的数据结构,类似二叉搜索树,我们把一些节点提取出来作为索引。如下:

在这里插入图片描述
在这里插入图片描述

我们提取了<13,19,25,34>作为一级索引,这样可以减少比较的次数。同样的,有一级索引就可以建立二级索引,如下,在海量的数据情况下这种方式无疑会大大减少查询的时间O(logN)

在这里插入图片描述
在这里插入图片描述

Redis中跳跃表的结构 在上面简单了解了跳跃表的基本含义及实现思想。在redis中,跳跃表的定义在 server.h 中,包含2个结构体,分别表示跳跃表节点的zskiplistNode和跳跃表zskilist。zskiplistNode 结构用于表示跳跃表节点,zskiplist结构用来保存跳跃表节点的相关信息。源码如下:

代码语言: javascript
复制
typedef struct zskiplistNode {
    //节点对应成员的对象,一般是SDS
    robj *obj;
    //分数,跳跃表的顺序按照分值进行排列
    double score;
    //存储后继节点的指针
    struct zskiplistNode *backward;
    // 层级
    struct zskiplistLevel {
        // 存储前驱节点的指针
        struct zskiplistNode *forward;
        // 跨度
        unsigned int span;
    } level[];
} zskiplistNode;
typedef struct zskiplist {
    // 跳跃表的表头节点和表尾节点
    struct zskiplistNode *header, *tail;
 
推荐文章
怕老婆的蟠桃  ·  求求你了,不要再自己实现这些逻辑了,开源工具类不香吗?(二)-阿里云开发者社区
2 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号