5分钟了解Redis的内部实现跳跃表(skiplist)

跳跃表简介

跳跃表(skiplist)是一个有序的数据结构,它通过在每个节点维护不同层次指向后续节点的指针,以达到快速访问指定节点的目的。跳跃表在查找指定节点时,平均时间复杂度为,最坏时间复杂度为O(N)。

Redis使用跳跃表(skiplist)作为有序集合(zset)的底层实现之一。当有序集合的元素个数大于等于 zset-max-ziplist-entries(默认为128个),或者每个元素成员的长度大于等于 zset-max-ziplist-value(默认为64字节)的时候,使用跳跃表和哈希表作为有序集合的内部实现。

举个例子,我们使用 zadd命令创建一个以跳跃表为实现的有序集合:

127.0.0.1:6379> zadd one-more-zset 1 long-long-long-long-long-long-long-long-long-long-long-long-long-long
(integer) 1
127.0.0.1:6379> zrange one-more-zset 0 -1
1) "long-long-long-long-long-long-long-long-long-long-long-long-long-long"
127.0.0.1:6379> object encoding one-more-zset
"skiplist"

跳跃表的实现

在Redis中的跳跃表是由 zskiplist结构表示的, zskiplist结构包含由多个跳跃表节点组成的双向链表,每一个跳跃表节点都保存着元素成员和对应的分钟。下面我们一个一个地详细了解一下。

zskiplist结构

跳跃表是由 zskiplist结构表示的,它包含以下几个属性:

  • header属性: 指向头部跳跃表节点的指针。
  • tail属性:指向尾部跳跃表节点的指针。
  • level属性:表示跳跃表中层数最大的节点的层数,表头节点的层数不计算在内。
  • length属性:表示跳跃表中的节点总数。

跳跃表节点的结构

跳跃表节点使用 zskiplistNode结构表示,它包含以下几个属性:

  • level属性:表示层的数组,数组中每个项使用 zskiplistLevel结构表示,它包含以下两个属性:
    *
  • forward属性:指向位于表尾方向其他节点的指针。
    *
  • span属性:当前节点到 forward指向的节点跨越了多少个节点。
  • backward属性:指向当前节点的前一个节点的指针。
  • obj属性:指向元素成员的指针。
  • score属性:当前元素成员对应的分数。

图解跳跃表

说了这么多,都比较抽象不容易理解,我们来举个例子:

5分钟了解Redis的内部实现跳跃表(skiplist)

这就是一个跳跃表的内部结构,其中有4个元素,键分别是:万、猫、学、社。

为什么不使用平衡树?

跳跃表以有序的方式在层次化的链表中保存元素, 在大多数情况下,跳跃表的效率可以和平衡树媲美,查找、删除、添加等操作都可以在对数期望时间下完成, 并且比起平衡树来说, 跳跃表的实现要简单直观得多。所以在Redis中没有使用平衡树,而是使用了跳跃表。

最后,谢谢你这么帅,还给我 点赞关注

微信公众号:万猫学社

微信扫描二维码

关注后回复「电子书

获取12本Java必读技术书籍

Original: https://www.cnblogs.com/heihaozi/p/16043956.html
Author: 万猫学社
Title: 5分钟了解Redis的内部实现跳跃表(skiplist)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/580948/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • mybatis插入时获取自增主键

    一、自增主键优缺点 1.优点 查询和插入的性能较高(增量增长,按序存放,具体可查看InnoDB相关资料了解B+树) 插入新记录时不用担心主键会重复 2.缺点 分布式系统中不太适用 …

    Java 2023年6月5日
    0108
  • JDBC学习笔记(一)

    Q:JDBC是什么? A: java DataBase Connectivity(java语言连接数据库),本质是sun公司制定的一套接口(interface) JDBC编程六步:…

    Java 2023年6月7日
    091
  • Fiddler高级用法

    Fiddler高级用法 1. 简单用法 Fiddler作为一个基于http协议的抓包工具,一直在业界有广泛使用。很多测试或者前端在使用Fiddler时,仅仅用于查看前端和服务端之间…

    Java 2023年6月13日
    058
  • SpringDataJpa学习

    # SpringBoot Jdbc JPAJPA是Java Persistence API的简称,&#x4E2…

    Java 2023年5月30日
    070
  • Java学习1——计算机基础知识

    计算机组成 计算机是由硬件系统和软件系统组成的 Windows常用快捷键 Ctrl+C——复制 Ctrl+V——粘贴 Ctrl+A——全选 Ctrl+S——保存 Ctrl+X——剪…

    Java 2023年6月5日
    069
  • java序列化和反序列化

    绕开transient机制的办法 虽然name被transient修饰,但是通过我们写的这两个方法依然能够使得name字段正确被序列化和反序列化writeObject和readOb…

    Java 2023年5月29日
    088
  • centos7更改中文

    这是在CentOS7中设置,CentOS6的是在 .etc/sysconfig/i18n 配置文件下。在root用户下操作,使用 locale 命令查看语言环境,看到 LANG=e…

    Java 2023年6月16日
    067
  • 解决Win10账户没有了管理员权限

    由于某些原因,当前用户账户没有了管理员权限或唯一的管理员账户被禁用,导致无法以管理员身份运行程序,或运行程序时提示需要输入管理员用户名或密码,但却没有输入窗口。这类情况下,需要进入…

    Java 2023年5月30日
    079
  • Elasticsearch 入门实战(3)–REST API 使用

    本文主要介绍 Elasticsearch REST API 的使用,相关的环境及软件信息如下:CentOS 7.6.1810、Elasticsearch 8.2.2。 1、REST…

    Java 2023年6月16日
    0106
  • POSIX 线程清理函数

    控制清理函数的函数有两个,一个是 pthread_cleanup_push(), 用来把清理函数压入栈中,另一个是 pthread_cleanup_pop(), 用来把栈中的函数弹…

    Java 2023年5月30日
    073
  • git没有提交的代码如何迁移到新建分支

    在接到需求以后,直接在master上开发了,到提交的时候才想起来忘记新建版本分支了,直接提交到master会影响到其他人。这时候就想着将本地编辑的代码,没有提交的代码暂存起来,然后…

    Java 2023年6月8日
    091
  • windows nginx配置https访问

    本文主要记录在windows下安装nginx 环境:win10-64位。 到nginx官网上下载相应的安装包,http://nginx.org/en/download.html; …

    Java 2023年5月30日
    082
  • 综合案例_创建数据库

    技术选型: web层: Servlet:前端控制器 html:视图 Filter:过滤器 BeanUtils:数据封装 jackson:json序列化工具 Service层 Jav…

    Java 2023年6月6日
    083
  • java-抽象类笔记

    抽象方法 使用 abstract 修饰的方法, 没有方法体,只有声明。 定义的是一种”规范”, 就是告诉子类必须要给抽象方法提供具体的实现。 抽象类 包含 …

    Java 2023年6月15日
    058
  • Effective Java 第三版—— 87. 考虑使用自定义序列化形式

    Tips书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code注意,书中的有些代码里方法是基于Java 9…

    Java 2023年5月29日
    064
  • DBeaver配置Hive连接(转)

    https://blog.csdn.net/weixin_44374374/article/details/123957815 posted on2022-07-26 10:52 …

    Java 2023年6月8日
    088
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球