当前位置: 首页 > news >正文

redis-跳跃表zskiplist

跳跃表结构介绍

跳跃表是在有序链表的基础上实现的一种数据结构。先看一下有序链表的结构:

如图所示的有序链表,如果要查询值为51的元素,需要从链表头开始依次查找,查找的效率是O(n)。有序链表的插入和删除都需要先找到合适的位置再修改next指针,修改操作基本不耗时,所以有序链表的插入、删除操作时间消耗主要在元素的查找上跳表就是在此基础上实现的一种优化方案。

如果我们将有序链表的部分节点分层,每一层的元素个数逐渐减少,并且每一层都是一个有序链表。在查找时优先从最高层开始向后查找,在到达某节点时,如果next节点值大于要查找的值或者next的值指向NULL,则从当前节点下降一层继续向后查找,这样就会提升查找效率。

图1:分层有序链表

假如我们还是查找值为51的节点,按照上述规则,则查找的思路如下:

图2

                                                                                     

1) 从第2层开始,1节点比51节点小,向后比较。
2) 21节点比51节点小,继续向后比较。第2层21节点的next指针指向NULL,所以从21节点开始需要下降一层到第1层继续向后比较。
3) 第1层中,21节点的next节点为41节点,41节点比51节点小,继续向后比较。第1层41节点的next节点为61节点,比要查找的51节点大,所以从41节点开始下降一层到第0层继续向后比较。
4) 在第0层,51节点为要查询的节点,节点被找到。

采用图2所示的数据结构后,总共查找4次就可以找到51节点,比有序链表少2次。当数据量大时,优势会更明显。 

综上所述,通过将有序集合的部分节点分层,由最上层开始依次向后查找,如果本层的next节点大于要查找的值或next节点为NULL,则从本节点开始,降低一层继续向后查找,依次类推,如果找到则返回节点;否则返回NULL。采用该原理查找节点,在节点数量比较多时,可以跳过一些节点,查询效率大大提升,这就是跳跃表的基本思想。

跳跃表的性质

跳表节点与结构

由以上分析我们知道,跳跃表由多个节点构成,每个节点由很多层构成,每层都有指向本层下个节点的指针。那么,Redis中 的跳跃表是如何实现的呢?

我们看下跳跃表节点的zskiplistNode结构体。redis6.0代码在server.h中定义

typedef struct zskiplistNode {
    sds ele;
    double score;
    struct zskiplistNode *backward;
    struct zskiplistLevel {
        struct zskiplistNode *forward;
        unsigned long span;
    } level[];
} zskiplistNode;

typedef struct zskiplist {
    struct zskiplistNode *header, *tail;
    unsigned long length;
    int level;
} zskiplist;

 

相关文章:

  • redis集群介绍与搭建
  • Linux系统命令与网络、磁盘参数和日志监控命令
  • mysql 8.0版本修改密码
  • 解决Navicat 连接mysql报错:Can‘t connect to MYSQL server on “ip address“(10061)
  • jsoncons使用之: 构造json
  • 使用reserve来避免不必要的内存重新分配
  • redis 编译报错 zmalloc.h:50:10: fatal error: jemalloc/jemalloc.h: 没有那个文件或目录
  • linux下hiredis安装、C接口编程
  • redis源码学习之数据结构---双向链表
  • redis源码分析--事件驱动模型
  • ubuntu下zmq编译安装及请求-应答模式测试
  • c++输出:怎么解决数字过大时默认使用科学计数法输出的问题?
  • c++11实现一个自动注册的工厂模式
  • zmq发布-订阅模式c++实现
  • linux报错:bash: syntax error near unexpected token `(‘ --路径中有括号怎么处理?
  • 【跃迁之路】【733天】程序员高效学习方法论探索系列(实验阶段490-2019.2.23)...
  • 10个确保微服务与容器安全的最佳实践
  • Django 博客开发教程 8 - 博客文章详情页
  • echarts的各种常用效果展示
  • idea + plantuml 画流程图
  • JS基础之数据类型、对象、原型、原型链、继承
  • k8s 面向应用开发者的基础命令
  • k个最大的数及变种小结
  • Meteor的表单提交:Form
  • oschina
  • php ci框架整合银盛支付
  • Redash本地开发环境搭建
  • Swift 中的尾递归和蹦床
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • vuex 学习笔记 01
  • 线性表及其算法(java实现)
  • 运行时添加log4j2的appender
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • ​ArcGIS Pro 如何批量删除字段
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • ​LeetCode解法汇总2304. 网格中的最小路径代价
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • ​ubuntu下安装kvm虚拟机
  • # Python csv、xlsx、json、二进制(MP3) 文件读写基本使用
  • #1014 : Trie树
  • #include
  • $L^p$ 调和函数恒为零
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (02)vite环境变量配置
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (3)nginx 配置(nginx.conf)
  • (Python第六天)文件处理
  • (附源码)springboot教学评价 毕业设计 641310
  • (一) storm的集群安装与配置
  • (转)自己动手搭建Nginx+memcache+xdebug+php运行环境绿色版 For windows版
  • .net core 6 集成和使用 mongodb
  • .net网站发布-允许更新此预编译站点
  • @Autowired标签与 @Resource标签 的区别
  • @软考考生,这份软考高分攻略你须知道
  • [ 2222 ]http://e.eqxiu.com/s/wJMf15Ku