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

Redis跳跃表

前言

        跳跃表(skiplist)是一种有序数据结构,它通过在每一个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。
        跳跃表支持平均O(logN),最坏O(N),复杂度的节点查找,还可以通过顺序性来批量处理节点。比如:取某个范围内的节点数据。在大部分情况下,跳跃表的效率可以和平衡树进行媲美,并且跳跃表的实现比平衡树简单。
        Redis使用跳跃表的使用不像链表和字典等数据结构被广泛应用。只有两个地方用到了跳跃表,一个是实现有序集合键,另外一个是在集群节点中用作内部数据结构。

        跳跃表查找时从level的最高层开始进行查找的。

一. 跳跃表的实现

        Redis跳跃表由server.h/zskilplistNode和server.h/zskiplist两个结构定义,其中zskilplistNode结构用于表示跳跃表节点,而zskiplist结构用于保存跳跃表节点相关信息,比如节点数量,以及指向表头节点和表尾节点的指针等。

        上图是一个跳跃表的示例,位于图片最左边的是zskiplist结构,该结构包含一下属性:

  • header: 指向跳跃表的表头节点
  • tail: 指向跳跃表的表尾节点
  • level: 记录目前跳跃表内,层数最大的那个节点的层数(表头节点不计算在内)
  • length: 记录跳跃表的长度,跳跃表目前包含的节点数量(表头节点不计算在内)。

         位于zskiplist结构右方的是四个zskiplistNode结构,该结构包含一下属性:

  • 层(level):  节点中使用L1,L2,L3等字样标记节点的各个层,L1表示第一层,L2表示第二次以此类推。每一层都带有两个属性: 前进指针和跨度。前进指针用于访问位于表尾方向的其他节点,而跨度则记录了前进指针指向节点和当前节点的距离。在上图中,带有数字的箭头代表前进指针,而那个数字就是跨度。当程序从表头向表尾遍历时,访问会沿着层的前进指针进行。
  • 后退指针(backward)指针: 节点中的BW字样标记节点的后退指针,它指向位于当前节点的前一个节点。后退指针在程序从表尾向表头遍历时使用。
  • 分值(score): 上图各个节点中的1.0,2.0和3.0是节点所保存的分值。在跳跃表中,节点按各自所保存的分支从小到大排列。
  • 成员对象(ele): 各个节点中的o1,o2和o3是节点所保存的成员对象。

        注意:表头节点和其他节点的构造一样,表头节点也有后退指针,分值和成员对象。不过表头节点的这些属性不会被用到,所以图中省略了这些部分,只显示了表头节点的各个层。

        1.1. 跳跃表节点

        跳跃表节点的实现由server.h/zskiplistNode结构定义:

/* ZSETs use a specialized version of Skiplists */
typedef struct zskiplistNode {//成员对象sds ele;//分值double score;//后退指针struct zskiplistNode *backward;//层struct zskiplistLevel {//前进指针struct zskiplistNode *forward;//跨度unsigned long span;} level[];
} zskiplistNode;
  • 层(level)

        跳跃表节点的level数组可以包含多个元素,每一个元素都包含一个指向其他节点的指针,程序可以通过这些层来加快访问其他节点的速度。一般来说,层的数量越多,访问其他节点的速度越快。因为每一层都会都可能会指向其他节点(成员)。

        每次创建一个新的跳跃表节点的时候,程序都更具幂次定律(power law,越大的数出现的概率越小),随机生成一个介于1和32之间的值作为level数组的大小。这个大小就是层的"高度"。

  • 前进指针

        每一层都有一个指向表尾方向的前进指针(level[i].forward属性),用于从表头向表尾方法访问节点。表尾节点的前置指针指向NULL。

        跳跃表查找是从最高层向下层查找的,当level[i].span为1,说明下一个节点是顺序的节点,当遍历到NULL时,说明遍历结束,下面虚线就是遍历方向。

  • 跨度 

        层的跨度(level[i].span属性)用于记录两个节点之间的距离。

  • 两个节点间的跨度越大,说明它们相距越远。
  • 指向NULL的所有前进指针的跨度为0,因为他们没有连接任何节点。

        跨度实际上是用来计算排位(rank)的:在查找某个节点的过程中,将沿途访问过的所有层的跨度累计起来,等到的结果就是目标节点在跳跃表中的排位。

        举个例子:在上图中要查找分值为3,成员对象为o3的节点时,沿途经过的层: 查找过程只经过一个层,并且层的跨度为3,所以目标节点在跳跃表中的排位为3。

  • 后退指针

        节点的后退指针(backward属性)用于从表尾向表头方向访问节点:跟可以一次跳过多个节点的前进指针不同,因为每一个节点只有一个后退指针,所以每次只能后退至前一个节点。

        在跳跃表结构中,通过tail指针获取表尾节点,在通过节点的backward指针向前遍历,直到backward指针为NULL。

  • 分值和成员

        节点的分值(score属性)是一个double类型的浮点数,跳跃表所有节点都按照分值从小到大排序。

        节点的成员(ele属性)是sds类型,是redis自己定义的动态字符串。

        在同一个跳跃表中,各个节点保存的成员对象必须唯一,但是多节点保存的分值可以相同,分值相同的节点按照成员对象(ele)在字典序中的大小来进行排序。成员对象字典序较小的节点会排在前面(靠近表头的方向),而成员对象在字典序中较大的节点会排在后面(靠近表尾方向)。

        1.2 跳跃表

        仅靠多个跳跃表节点就可以组成一个跳跃表。但通过使用一个zskiplist结构来持有这些节点,程序可以更加方便地对整个跳跃表进行处理。比如:快熟访问跳跃表表头节点和表尾节点,或者获得跳跃表节点数量等信息。

typedef struct zskiplist {//表头节点/表尾节点struct zskiplistNode *header, *tail;//表中节点个数unsigned long length;//表中层数最大节点的层数int level;
} zskiplist;

        header和tail指针已经指向跳跃表的表头和表尾,通过这两个指针获得跳跃表的表头和表尾节点时间复杂度为O(1)

        通过length属性来记录节点数量。程序可以在O(1)时间复杂度内返回跳跃表的长度。

        level则可以在O(1)时间复杂度内获得跳跃表层数最高节点的层数量,注意,不包括表头节点。

二.跳跃表API

相关文章:

Redis跳跃表

前言 跳跃表(skiplist)是一种有序数据结构,它通过在每一个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。 跳跃表支持平均O(logN),最坏O(N),复杂度的节点查找,还可以通过顺序性来批量处理节点…...

C++基础从0到1入门编程(二)

系统学习C 方便自己日后复习,错误的地方希望积极指正 往期文章:C基础从0到1入门编程(一) 参考视频: 1.黑马程序员匠心之作|C教程从0到1入门编程,学习编程不再难 2.系统化学习C 1 函数指针和回调函数 如果把函数的地址…...

Uniapp扫码预览连接地址与手机不在同一网段

在开发Uniapp应用时,这里有一个扫码预览的功能,电脑与手机都是在一网络下,之前点开后预览地址一直是169.254.3.x的地址,通过WINR键输入cmd运行,然后ipconfig查看所有网络连接。发现有一个虚拟网络连接的地址是169.251.…...

万界星空科技SMT行业生产管理MES系统解决方案

一、SMT行业特点: SMT(Surface Mounted Technology)作为电子组装行业里首先的技术和工艺,选择合适的MES解决方案来保障SMT生产的成功至关重要。 电子行业涉及的范围非常广,包含了汽车、电脑、电视、手机等产品上&…...

vue3 uniapp h5 安卓和iOS开发适配踩坑记录

font-size适配屏幕大小及iOS和安卓状态栏及安全距离的处理 App.vue <script setup lang"ts"> import { onLaunch, onShow, onHide } from "dcloudio/uni-app"; import ./main.scss onLaunch(() > {console.log("App Launch");var wid…...

inf和nan

在某些编程语法中inf表示无穷大,nan表示不是一个数(not a number) nan表示这个数不确定,而无穷大表示这个数任意大 1/0inf 这里把0当做一个无限接近0,但是非0的数 5-inf-inf 一个数减去无穷大会等于负无穷大 而inf-infnan 因为两个无穷大相减有很多可能,可能等于一个常数,也可能…...

十. Linux关机重启命令与Vim编辑的使用

关机重启命令 shutdown命令 其他关机命令 其他重启命令 系统运行级别 系统默认运行级别与查询 退出登录命令logout 文本编辑器Vim Vim简介 没有菜单,只有命令Vim工作模式 Vim常用命令 插入命令 定位命令 删除命令 复制和剪切命令 替换和取消命令 搜索和搜索替换命令 保存和退出…...

Spring-IOC-@Value和@PropertySource用法

1、Book.java PropertySource(value"classpath:配置文件地址") 替代 <context:property-placeholder location"配置文件地址"/> Value("${book.bid}") Value("${book.bname}") Value("${book.price}") <bean id&…...

如何理解Python中一切皆对象?

Python 一、示例代码二、Python中的魔法方法 一、示例代码 有理数类 import mathclass rational:def __init__(self,p,q):self.p pself.q qdef __str__(self):return "{} / {}".format(self.p,self.q)def simplify(self):gcd math.gcd(self.p,self.q)return rat…...

【如何学习Python自动化测试】—— 鼠标键盘操作

5 、 鼠标键盘操作 在浏览器中&#xff0c;通常会用到鼠标来进行操作&#xff0c;比如右键菜单中选择一个操作&#xff0c;在 selenium 中提供了下列鼠标相关操作。 ActionChains 类提供了以下方法&#xff1a; 点击鼠标&#xff1a;click()右击鼠标&#xff1a;context…...

随笔-事儿就这么个事儿

好久没写了&#xff0c;小A要催更&#xff0c;还答应让我写一下他的经历&#xff0c;这还有啥说的&#xff0c;开整。 1、升级 前段时间登录公司的办公系统处理一个事务申请&#xff0c;发现有个粗体标红的通知&#xff0c;是关于今年的晋升名单公示。进去看了一眼&#xff0…...

django理解03 数据库引入

配置 settings.py DATABASES {"default": {"ENGINE": "django.db.backends.mysql",NAME:307_django_db,USER: root,PASSWORD: 123456,HOST: 127.0.0.1,PORT: 3306,} }先创建指定名称的数据库databases create database self_django_db DEFAUL…...

Jtti:windows中apache怎么实现负载均衡

Jtti&#xff1a;windows中apache怎么实现负载均衡 在Windows环境下&#xff0c;你可以使用Apache HTTP Server搭建负载均衡集群。Apache提供了一个模块叫做mod_proxy&#xff0c;它可以用来实现反向代理和负载均衡。以下是一个简单的步骤来配置Apache负载均衡&#xff1a; 步骤…...

2311rust,到43版本更新

1.38.0 流水编译 要编译仓库,编译器不需要完全构建依赖项.相反,只需要它们的"元数据"(即类型,依赖关系,导出列表). 在编译过程的早期生成此元数据.从Rust1.38.0开始,Cargo利用这一点,在准备好元数据后立即自动开始构建依赖的仓库. 检查错误使用mem::{uninitialize…...

前端埋点上报的几种方式

现代Web应用程序中&#xff0c;埋点上报是一种重要的数据收集和分析手段。本文将介绍前端埋点上报的几种常见方式&#xff0c;并详细阐述如何在项目中运用这些方式进行数据上报&#xff0c;以帮助开发者更好地进行数据收集和分析。 上报方式 在前端中&#xff0c;常见的埋点上…...

外部 prometheus监控k8s集群资源

prometheus监控k8s集群资源 一&#xff0c;通过CADvisior 监控pod的资源状态1.1 授权外边用户可以访问prometheus接口。1.2 获取token保存1.3 配置prometheus.yml 启动并查看状态1.4 Grafana 导入仪表盘 二&#xff0c;通过kube-state-metrics 监控k8s资源状态2.1 部署 kube-st…...

centos安装神通数据库

1、安装 wget工具 yum install -y wget2、安装rar解压工具 wget --no-check-certificate http://www.rarlab.com/rar/rarlinux-x64-5.3.0.tar.gz tar zxvf rarlinux-x64-5.3.0.tar.gz && cd rar/ && make install3、下载oscar神通数据库&#xff08;linux 64…...

汇编-PUSHFD和POPFD标志寄存器值压栈和出栈

PUSHFD指令将32位EFLAGS寄存器内容压入堆栈&#xff0c; 而POPFD指令则将栈顶单元内容弹出到EFLAGS寄存器 格式&#xff1a;...

基于SSM的进销存管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…...

Django DRF限流组件

在DRF中&#xff0c;限流发生在认证、权限之后&#xff0c;限流组件的使用步骤&#xff1a; 1、编写自定义限流类&#xff1b; 2、在settings.py中配置redis&#xff1b; 3、安装django-redis; 4、启动redis服务&#xff1b; 5、局部应用&#xff0c;一般是在核心的视图中使用&…...

【稀缺资源】AISMM 2.1评估矩阵首次公开:12项技术品牌健康度诊断+即时生成个人IP升级路线图

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AISMM模型与技术品牌塑造 AISMM&#xff08;Artificial Intelligence Strategy Maturity Model&#xff09;是一种面向AI驱动型组织的技术战略成熟度评估框架&#xff0c;它将技术品牌塑造视为组织能力…...

告别手动续期!用acme.sh + Nginx搞定Let‘s Encrypt免费SSL证书(保姆级配置流程)

零门槛实现HTTPS自动化&#xff1a;acme.sh与Nginx的完美协作指南 第一次部署个人博客时&#xff0c;我盯着浏览器地址栏那个刺眼的"不安全"警告整整三天。直到发现Lets Encrypt的免费证书&#xff0c;才意识到原来HTTPS配置可以如此简单。但三个月后&#xff0c;当深…...

JetBrains IDE试用期重置终极指南:2026年开源解决方案详解

JetBrains IDE试用期重置终极指南&#xff1a;2026年开源解决方案详解 【免费下载链接】ide-eval-resetter 项目地址: https://gitcode.com/gh_mirrors/id/ide-eval-resetter 你是否曾经在项目开发的关键时刻&#xff0c;突然被JetBrains IDE弹出的试用期结束提示打断思…...

Termi AI:基于Electron的智能桌面开发伴侣,集成Vite预览与AI编程助手

1. 项目概述&#xff1a;一个集成了AI助手的桌面开发伴侣如果你和我一样&#xff0c;每天大部分时间都泡在终端和编辑器里&#xff0c;那你肯定也幻想过&#xff1a;能不能有一个工具&#xff0c;能把我的项目实时预览和AI编程助手无缝地“焊”在一起&#xff1f;不用在浏览器、…...

【EAI(企业应用集成)工具】Asteria warp簡単紹介(アステリア ワープ)

目录 ■前言 ■Asteria warp簡単紹介 ■ASTERIA Warpとは ■ASTERIA Warp 命名哲学 ■ASTERIA WARPについて ■19年連続国内シェアNo.1 ■10,000社以上の企業での導入実績 ■ノーコードだから誰でも使える ■市场地位&#xff1a;日本市场的绝对王者 ■核心产品力&am…...

自动驾驶仿真训练平台SIMSCALE的技术解析与应用实践

1. 项目背景与核心价值去年参与某自动驾驶研发项目时&#xff0c;我们团队遇到了真实路测成本高、极端场景覆盖难的问题。当时每天要花费数万元进行车队路测&#xff0c;但遇到暴雨天气或特殊交通状况时&#xff0c;数据采集效率直线下降。正是这种困境让我开始关注仿真技术在自…...

vscode-dark-islands的命令面板美化:玻璃态边框与圆角设计

vscode-dark-islands的命令面板美化&#xff1a;玻璃态边框与圆角设计 【免费下载链接】vscode-dark-islands VSCode theme based off the easemate IDE and Jetbrains islands theme 项目地址: https://gitcode.com/GitHub_Trending/vs/vscode-dark-islands vscode-dar…...

CSharpier代码生成器揭秘:自动生成语法节点打印器的实现原理

CSharpier代码生成器揭秘&#xff1a;自动生成语法节点打印器的实现原理 【免费下载链接】csharpier CSharpier is an opinionated code formatter for c#. 项目地址: https://gitcode.com/gh_mirrors/cs/csharpier CSharpier是一款针对C#的代码格式化工具&#xff0c;它…...

Gitee SCA:为企业级开源治理构筑自动化防线

在数字化转型的大潮中&#xff0c;开源软件已成为企业技术栈不可或缺的组成部分。最新行业数据显示&#xff0c;全球范围内超过90%的企业在软件开发过程中依赖开源组件&#xff0c;这一比例在中国市场同样居高不下。然而&#xff0c;开源组件的广泛使用也带来了新的安全挑战——…...

Gemini和ChatGPT同时要开始投广告了:AI聊天机器人的“免费午餐“时代终结

Gemini和ChatGPT同时要开始投广告了&#xff1a;AI聊天机器人的"免费午餐"时代终结 导语 5月2日&#xff0c;谷歌母公司Alphabet在财报电话会议上释放了一个明确信号&#xff1a;Gemini未来将引入广告业务。 首席商务官Philipp Schindler的原话是&#xff1a;“广告是…...