热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

redis跳表

文章目录zset跳表复杂度为什么选择了跳跃表而不是红黑树zsetzset是可排序的set。与hash的实现方式类似,如果元素个数不多且不大,就使用压缩


文章目录

  • zset
  • 跳表
  • 复杂度
  • 为什么选择了跳跃表而不是红黑树


zset

zset是可排序的set。与hash的实现方式类似,如果元素个数不多且不大,就使用压缩列表ziplist来存储。不过由于zset包含了score的排序信息,所以在ziplist内部,是按照score排序递增来存储的。意味着每次插入数据都要移动之后的数据。


跳表

跳表(skiplist)是另一种实现dict的数据结构。跳表是对链表的一个增强。我们在使用链表的时候,即使元素的有序排列的,但如果要查找一个元素,也需要从头一个个查找下去,时间复杂度是O(N)。而跳表顾名思义,就是跳跃了一些元素,可以抽象多层。

如下图所示,比如我们要查找8,先在最上层L2查找,发现在1和9之间;然后去L1层查找,发现在5和9之间;然后去L0查找,发现在7和9之间,然后找到8。

当元素比较多时,使用跳表可以显著减少查找的次数。
在这里插入图片描述
同list类似,Redis内部也不是直接使用的跳表,而是使用了一个自定义的数据结构来持有跳表。下图左边蓝色部分是skiplist,右边是4个zskiplistNode。zskiplistNode内部有很多层L1、L2等,指针指向这一层的下一个结点。BW是回退指针(backward),用于查找的时候回退。然后下面是score和对象本身object。
在这里插入图片描述
在这里插入图片描述
可以看到一个是dict结构,主要key是其集合元素,而value就是对应分值,而zkiplist作为跳跃表,按照分值排序,方便定位成员
在这里插入图片描述
在这里插入图片描述
zskiplistNode中的robj指针指向具体元素,注意这个指针和dict中key指针指向同一个元素,其中backward后腿指针便于回溯


复杂度

第一层索引节点n/2,第二层索引节点n/4,第三层索引节点n/8,以此类推第n层节点n 得到h=logn - 1。
由上图可以知道&#xff0c;当我们要找到8号这个节点的时候&#xff0c;我们在k级索引发现5<8<9&#xff0c;故我们要到k-1索引下找&#xff0c;但是发现7<8<9,故我们要到原始链表找&#xff0c;且k索引层最多遍历1&#xff0c;5&#xff0c;9三个节点&#xff0c;k-1最多遍历5&#xff0c;7&#xff0c;9三个节点&#xff0c;故跳表的时间复杂度为O(3logn)&#61;O(logn),索引节点总数为&#xff1a;n/2 &#43; n/4 &#43; n/8 &#43; … &#43; 8 &#43; 4 &#43; 2 &#61;n&#xff0c;故空间复杂度为O(n)


为什么选择了跳跃表而不是红黑树


  1. 在做范围查找的时候&#xff0c;平衡树比skiplist操作要复杂。在平衡树上&#xff0c;我们找到指定范围的小值之后&#xff0c;还需要以中序遍历的顺序继续寻找其它不超过大值的节点。如果不对平衡树进行一定的改造&#xff0c;这里的中序遍历并不容易实现。而在skiplist上进行范围查找就非常简单&#xff0c;只需要在找到小值之后&#xff0c;对第1层链表进行若干步的遍历就可以实现
  2. 平衡树的插入和删除操作可能引发子树的调整&#xff0c;逻辑复杂&#xff0c;而skiplist的插入和删除只需要修改相邻节点的指针&#xff0c;操作简单又快速。
  3. 从内存占用上来说&#xff0c;skiplist比平衡树更灵活一些。一般来说&#xff0c;平衡树每个节点包含2个指针&#xff08;分别指向左右子树&#xff09;&#xff0c;而skiplist每个节点包含的指针数目平均为1/(1-p)&#xff0c;具体取决于参数p的大小。如果像Redis里的实现一样&#xff0c;取p&#61;1/4&#xff0c;那么平均每个节点包含1.33个指针&#xff0c;比平衡树更有优势。
  4. 查找单个key&#xff0c;skiplist和平衡树的时间复杂度都为O(log n)&#xff0c;大体相当&#xff1b;而哈希表在保持较低的哈希值冲突概率的前提下&#xff0c;查找时间复杂度接近O(1)&#xff0c;性能更高一些。所以我们平常使用的各种Map或dictionary结构&#xff0c;大都是基于哈希表实现的。
  5. 从算法实现难度上来比较&#xff0c;skiplist比平衡树要简单得多

参考
https://blog.csdn.net/qq_38286618/article/details/102530020
https://blog.csdn.net/weixin_39030846/article/details/112433527
https://www.cnblogs.com/cjjjj/p/12751487.html (redis为什么选择了跳跃表而不是红黑树)


推荐阅读
  • 在List和Set集合中存储Object类型的数据元素 ... [详细]
  • 服务器部署中的安全策略实践与优化
    服务器部署中的安全策略实践与优化 ... [详细]
  • 技术日志:使用 Ruby 爬虫抓取拉勾网职位数据并生成词云分析报告
    技术日志:使用 Ruby 爬虫抓取拉勾网职位数据并生成词云分析报告 ... [详细]
  • 本文探讨了 Java 中 Pair 类的历史与现状。虽然 Java 标准库中没有内置的 Pair 类,但社区和第三方库提供了多种实现方式,如 Apache Commons 的 Pair 类和 JavaFX 的 javafx.util.Pair 类。这些实现为需要处理成对数据的开发者提供了便利。此外,文章还讨论了为何标准库未包含 Pair 类的原因,以及在现代 Java 开发中使用 Pair 类的最佳实践。 ... [详细]
  • 属性类 `Properties` 是 `Hashtable` 类的子类,用于存储键值对形式的数据。该类在 Java 中广泛应用于配置文件的读取与写入,支持字符串类型的键和值。通过 `Properties` 类,开发者可以方便地进行配置信息的管理,确保应用程序的灵活性和可维护性。此外,`Properties` 类还提供了加载和保存属性文件的方法,使其在实际开发中具有较高的实用价值。 ... [详细]
  • 本文深入解析了JDK 8中HashMap的源代码,重点探讨了put方法的工作机制及其内部参数的设定原理。HashMap允许键和值为null,但键为null的情况只能出现一次,因为null键在内部通过索引0进行存储。文章详细分析了capacity(容量)、size(大小)、loadFactor(加载因子)以及红黑树转换阈值的设定原则,帮助读者更好地理解HashMap的高效实现和性能优化策略。 ... [详细]
  • 为了确保iOS应用能够安全地访问网站数据,本文介绍了如何在Nginx服务器上轻松配置CertBot以实现SSL证书的自动化管理。通过这一过程,可以确保应用始终使用HTTPS协议,从而提升数据传输的安全性和可靠性。文章详细阐述了配置步骤和常见问题的解决方法,帮助读者快速上手并成功部署SSL证书。 ... [详细]
  • 在配置Nginx的SSL证书后,虽然HTTPS访问能够正常工作,但HTTP请求却会遇到400错误。本文详细解析了这一问题,并提供了Nginx配置的具体示例。此外,还深入探讨了DNS服务器证书、SSL证书的申请与安装流程,以及域名注册、查询方法和CDN加速技术的应用,帮助读者全面了解相关技术细节。 ... [详细]
  • V8不仅是一款著名的八缸发动机,广泛应用于道奇Charger、宾利Continental GT和BossHoss摩托车中。自2008年以来,作为Chromium项目的一部分,V8 JavaScript引擎在性能优化和技术创新方面取得了显著进展。该引擎通过先进的编译技术和高效的垃圾回收机制,显著提升了JavaScript的执行效率,为现代Web应用提供了强大的支持。持续的优化和创新使得V8在处理复杂计算和大规模数据时表现更加出色,成为众多开发者和企业的首选。 ... [详细]
  • 本文介绍了如何利用ObjectMapper实现JSON与JavaBean之间的高效转换。ObjectMapper是Jackson库的核心组件,能够便捷地将Java对象序列化为JSON格式,并支持从JSON、XML以及文件等多种数据源反序列化为Java对象。此外,还探讨了在实际应用中如何优化转换性能,以提升系统整体效率。 ... [详细]
  • 在Ubuntu上安装MySQL时解决缺少libaio.so.1错误及libaio在MySQL中的重要性分析
    在Ubuntu系统上安装MySQL时,遇到了缺少libaio.so.1的错误。本文详细介绍了如何解决这一问题,并深入探讨了libaio库在MySQL性能优化中的重要作用。对于初学者而言,理解这些依赖关系和配置步骤是成功安装和运行MySQL的关键。通过本文的指导,读者可以顺利解决相关问题,并更好地掌握MySQL在Linux环境下的部署与管理。 ... [详细]
  • 本指南从零开始介绍Scala编程语言的基础知识,重点讲解了Scala解释器REPL(读取-求值-打印-循环)的使用方法。REPL是Scala开发中的重要工具,能够帮助初学者快速理解和实践Scala的基本语法和特性。通过详细的示例和练习,读者将能够熟练掌握Scala的基础概念和编程技巧。 ... [详细]
  • Java学习第10天:深入理解Map接口及其应用 ... [详细]
  • 在使用 Cacti 进行监控时,发现已运行的转码机未产生流量,导致 Cacti 监控界面显示该转码机处于宕机状态。进一步检查 Cacti 日志,发现数据库中存在 SQL 查询失败的问题,错误代码为 145。此问题可能是由于数据库表损坏或索引失效所致,建议对相关表进行修复操作以恢复监控功能。 ... [详细]
  • 每年,意甲、德甲、英超和西甲等各大足球联赛的赛程表都是球迷们关注的焦点。本文通过 Python 编程实现了一种生成赛程表的方法,该方法基于蛇形环算法。具体而言,将所有球队排列成两列的环形结构,左侧球队对阵右侧球队,首支队伍固定不动,其余队伍按顺时针方向循环移动,从而确保每场比赛不重复。此算法不仅高效,而且易于实现,为赛程安排提供了可靠的解决方案。 ... [详细]
author-avatar
dsjdsjdsjjk_896
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有