Redis数据结构之跳跃表-skiplist
在Redis
中,zset
是一个复合结构:
使用
hash
来存储value
和score
的映射关系使用跳跃表来提供按照
score
进行排序的功能,同时可以指定score
范围来获取value
列表
结构
zset
内部是一个hash
字典加一个跳跃表skiplist
struct zslnode {
string value;
double score;
zslnode *[]forwards; // 多层连接指针
zslnode *backward // 回溯指针
} zslnode;
struct zsl {
zslnode *header; // 跳跃表头指针
int maxLevel; // 跳跃表当前最高层
map<string, zslnode*> ht; // hash结构的所有键值对
} zsl;
图为跳跃表示意图,实际上在Redis
中共有64
层,即最多可容纳2^64
个元素。
每一个kv
块即代码中zslnode
,header
中value
为NULL
值,score
为Double.MIN_VALUE
。kv
之间使用指针链接成为双向链表,这些键值对根据score
进行有序排列,不同的kv
层高可能不同,层数越高则kv
越少,同一层的kv
之间使用指针进行串接,对于每一层的元素的遍历都是从kv header
出发的。
常用操作
查找
如图所示,需要定位紫色的kv
时,首先从header
最高层开始进行遍历,遍历到第一个比k
值小的节点,然后下降一层继续查找该层最后一个比k
小的元素,依此类推,直到查找到该元素为止。
搜索时中间的一系列节点称之为搜索路径,它是从最高层一直到最底层的每一层最后一个比目标节点小的元素节点列表。
插入
插入新节点时,首先需要搜索合适的插入点,类似于查找过程找到合适节点之后就可以开始创建新的节点。创建时需要为节点随机分配一个层数,再将搜索路径上的节点和新节点通过前后指针进行串接。
如果分配的新的节点比当前跳跃表最大高度高的话,需要更新一下跳跃表的最大高度。
删除
删除过程和插入过程类似,需要先将搜索路径找出来,然后对于每一个层的相关节点,都需要重排一下前后指针,同时注意更新一下最高层数maxLevel
。
更新
调用zadd
方法时,如果对应的value
不存在,直接进行插入;如果已经存在且只是更新score
的话,需要进行更新。
如果新值的score
不会带来排序位置的改变,则不需要调整位置,直接修改元素的score
值即可,否则需要调整该节点位置。
Redis
在更新节点位置时,采用先删除这个元素,再插入这个元素的方法,这样就不需要判断是否需要调整位置,只需要进行两次路径搜索即可。
如果score
值一样
极端情况下,zset
中所有元素的score
一样,此时查找性能也不会退化为O(n)
,因为zset
的排序不只考虑score
,如果score
一样的话还会再比较value
值。
计算元素排名
zset
可以使用rank
获取元素排名,主要是因为Redis
中,对于skiplist
的节点的forward
指针进行了优化,给每一个forward
指针添加了span
属性,表示从前一个节点沿当前层的forward
指针跳到当前节点时中间会跳过多少个节点。
借助span
属性,在计算一个元素的排名时,只需要将搜索路径上经过的所有节点的span
属性进行叠加即可计算出最终的rank
值。
Redis数据结构之跳跃表-skiplist的更多相关文章
- Redis数据结构之跳跃表
跳跃表是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的. 一.跳跃表结构定义1. 跳跃表节点结构定义: 2. 跳跃表结构定义: 示例: 二.跳跃表节点中各种 ...
- Redis数据结构:跳跃表
1. 跳跃表是有序集合(zset)的底层实现之一: 2. 由zskiplist和zskiplistNode组成: 3. 每个跳跃表节点的层数都是1-32之间的随机数(每创建一个节点的时候,程序会随机生 ...
- redis 系列7 数据结构之跳跃表
一.概述 跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的.在大部分情况下,跳跃表的效率可以和平衡树(关系型数据库的索引就是平衡树 ...
- Redis 的底层数据结构(跳跃表)
字典相对于数组,链表来说,是一种较高层次的数据结构,像我们的汉语字典一样,可以通过拼音或偏旁唯一确定一个汉字,在程序里我们管每一个映射关系叫做一个键值对,很多个键值对放在一起就构成了我们的字典结构. ...
- redis源码分析之数据结构:跳跃表
跳跃表是一种随机化的数据结构,在查找.插入和删除这些字典操作上,其效率可比拟于平衡二叉树(如红黑树),大多数操作只需要O(log n)平均时间,但它的代码以及原理更简单. 和链表.字典等数据结构被广泛 ...
- Redis 底层数据结构之跳跃表
文章参考 <Redis 设计与实现>黄建宏 Redis(2) 跳跃表 跳跃表 跳跃表 skiplist 是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节 ...
- Redis 为什么使用跳跃表
引言 跳跃表是一种有序的数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的. 什么是跳跃表 对于一个单链表来讲,即便链表中存储的数据是有序的,如果我们要想在其中查找某个 ...
- 存储系统的基本数据结构之一: 跳表 (SkipList)
在接下来的系列文章中,我们将介绍一系列应用于存储以及IO子系统的数据结构.这些数据结构相互关联又有着巨大的区别,希望我们能够不辱使命的将他们分门别类的介绍清楚.本文为第一节,介绍一个简单而又有用的数据 ...
- redis 5.0.7 源码阅读——跳跃表skiplist
redis中并没有专门给跳跃表两个文件.在5.0.7的版本中,结构体的声明与定义.接口的声明在server.h中,接口的定义在t_zset.c中,所有开头为zsl的函数. 一.数据结构 单个节点: t ...
随机推荐
- assets和static
相同点: assets和static两个都是存放静态资源文件.项目中所需要的资源文件图片,字体图标,样式文件等都可以放在这两个文件下. 不相同点: assets中存放的静态资源文件在项目打包时,也就是 ...
- 现在就去100offer 参加互联网人才拍卖! 现在登录现在注册 为什么整个互联网行业都缺前端工程师?
现在,几乎整个互联网行业都缺前端工程师,不仅在刚起步的创业公司,上市公司乃至巨头,这个问题也一样存在.没错,优秀的前端工程师简直比大熊猫还稀少. 每天,100offer的HR群都有人在吐槽招不到前端工 ...
- MYSQL索引的深入学习
通常大型网站单日就可能会产生几十万甚至几百万的数据,对于没有索引的表,单表查询可能几十万数据就是瓶颈. 一个简单的对比测试 以我去年测试的数据作为一个简单示例,20多条数据源随机生成200万条数据,平 ...
- 欧拉函数(Euler_Function)
一.基本概述在数论,对正整数n,欧拉函数varphi(n)是少于或等于n的数中与n互质的数的数目.此函数以其首名研究者欧拉命名,它又称为Euler's totient function.φ函数.欧拉商 ...
- Neo4j数据库学习一:安装和数据类型常用命令简介
Neo4j数据库是图数据库 在数据库中,只有节点Nodes和关系Relationships Nodes用圆圈表示,Relationships用有向箭头表示 关系和节点都有属性(键值对) 安装3.3.7 ...
- shell脚本命令行参数里的空白符
看一个小脚本 #!/bin/bash #demonstarting the shift command count= while [ -n "$1" ] ; do echo &qu ...
- su - 运行替换用户和组标识的shell
SYNOPSIS(总览) su [OPTION]... [-] [USER [ARG]...] DESCRIPTION(描述) 修改有效用户标识和组标识为USER的. -, -l, --login 使 ...
- VUE.JS 环境配置
首先安装 node.js 网址 https://nodejs.org/en/ 选择版本 点击直接安装OK (不用安装到系统盘) 然后cmd 命令框 输入 npm -version (查看安装版本 ...
- 前端学习(十三)js运算符(笔记)
类型转换: 1.强制类型转换:(数字字符串转数字) parseInt() parseFloat() Number()--严格转换 NaN: 不是 ...
- 说一下HTML5与传统HTML的区别
1.首先说一下什么是HTML5 HTML5 将成为 HTML.XHTML 以及 HTML DOM 的新标准. HTML 的上一个版本诞生于 1999 年.自从那以后,Web 世界已经经历了巨变. HT ...