Redis中,zset是一个复合结构:

  • 使用hash来存储valuescore的映射关系

  • 使用跳跃表来提供按照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块即代码中zslnodeheadervalueNULL值,scoreDouble.MIN_VALUEkv之间使用指针链接成为双向链表,这些键值对根据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的更多相关文章

  1. Redis数据结构之跳跃表

    跳跃表是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的. 一.跳跃表结构定义1. 跳跃表节点结构定义: 2. 跳跃表结构定义: 示例: 二.跳跃表节点中各种 ...

  2. Redis数据结构:跳跃表

    1. 跳跃表是有序集合(zset)的底层实现之一: 2. 由zskiplist和zskiplistNode组成: 3. 每个跳跃表节点的层数都是1-32之间的随机数(每创建一个节点的时候,程序会随机生 ...

  3. redis 系列7 数据结构之跳跃表

    一.概述 跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的.在大部分情况下,跳跃表的效率可以和平衡树(关系型数据库的索引就是平衡树 ...

  4. Redis 的底层数据结构(跳跃表)

    字典相对于数组,链表来说,是一种较高层次的数据结构,像我们的汉语字典一样,可以通过拼音或偏旁唯一确定一个汉字,在程序里我们管每一个映射关系叫做一个键值对,很多个键值对放在一起就构成了我们的字典结构. ...

  5. redis源码分析之数据结构:跳跃表

    跳跃表是一种随机化的数据结构,在查找.插入和删除这些字典操作上,其效率可比拟于平衡二叉树(如红黑树),大多数操作只需要O(log n)平均时间,但它的代码以及原理更简单. 和链表.字典等数据结构被广泛 ...

  6. Redis 底层数据结构之跳跃表

    文章参考 <Redis 设计与实现>黄建宏 Redis(2) 跳跃表 跳跃表 跳跃表 skiplist 是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节 ...

  7. Redis 为什么使用跳跃表

    引言 跳跃表是一种有序的数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的. 什么是跳跃表 对于一个单链表来讲,即便链表中存储的数据是有序的,如果我们要想在其中查找某个 ...

  8. 存储系统的基本数据结构之一: 跳表 (SkipList)

    在接下来的系列文章中,我们将介绍一系列应用于存储以及IO子系统的数据结构.这些数据结构相互关联又有着巨大的区别,希望我们能够不辱使命的将他们分门别类的介绍清楚.本文为第一节,介绍一个简单而又有用的数据 ...

  9. redis 5.0.7 源码阅读——跳跃表skiplist

    redis中并没有专门给跳跃表两个文件.在5.0.7的版本中,结构体的声明与定义.接口的声明在server.h中,接口的定义在t_zset.c中,所有开头为zsl的函数. 一.数据结构 单个节点: t ...

随机推荐

  1. upc组队赛2 Super-palindrome【暴力枚举】

    Super-palindrome 题目描述 You are given a string that is consisted of lowercase English alphabet. You ar ...

  2. Java web后台插入数据库中文乱码问题解决

    前言:项目想要避免乱码情况的出现,要保持服务器.数据库.项目.以及前端编码一致.一.项目以及前端编码,设置. myeclipse--->右键项目--->Properties--->R ...

  3. css点击高亮

    .btn-default:active:focus, .btn-default:active:hover { color: #333; background-color:lightseagreen; ...

  4. 力扣算法——135Candy【H】

    老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分. 你需要按照以下要求,帮助老师给这些孩子分发糖果: 每个孩子至少分配到 1 个糖果.相邻的孩子中,评分高 ...

  5. Java学习第一次总结

    在此之前我需要声明一下,我不载过多的评论知识点的简单与难易程度.写出来只是为了方便使用,现阶段追求的是实在.㈠①自动类型转换由低到高byte.short.char→int→long→flot→doub ...

  6. Python之字符串正则匹配

    需求: 正则表达式匹配某个文本模式,但是它找到的是模式的最长可能匹配(因为是贪婪匹配 ). 而你想修改它变成查找最短的可能匹配. import re text2 = 'Computer says &q ...

  7. JQuery 全选 反选 获取Table 中指定td的元素值

    //全选 function initTableCheckbox() { var $thr = $('table thead tr'); var $checkAllTh = $('<th>& ...

  8. Validation Engine 表单验证

    前端开发仓库 » jQuery » jQuery Validation Engine 表单验证 jQuery Validation Engine 表单验证来源 功能强大的 jQuery 表单验证插件, ...

  9. 如何取消IDEA的自动删除行尾空格?

    使用IDEA,添加注释的时候敲空格,总是会把行尾空格删除导致代码跑到注释行,很不爽~~ 取消这个不爽的功能:File--Settings--Editor--General--Other--Strip ...

  10. 2019-8-31-How-to-use-code-to-exit-the-application-in-UWP

    title author date CreateTime categories How to use code to exit the application in UWP lindexi 2019- ...