百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

【Redis数据结构·跳跃表】之异火排行榜

mhr18 2024-11-27 12:06 24 浏览 0 评论

在面试中,Redis是面试官最喜欢问的话题,而跳跃表则是Redis中比较复杂的数据结构,读完本文相信掘友定有提升,还望支持一波~

跳跃表是什么

跳跃表(skiplist)一种有序数据结构。它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。

跳跃表与链表不同的地方在于:链表每个节点只有指向头、尾两个指针;而跳跃表每个节点可能有更多的指针,指集合键的节点便于快速的遍历。

从这里我们也可以看出跳跃表是一个空间换时间的一种模型。

它的时间复杂度为O(log N)、最坏O(N)。跳跃表和红黑树的时间复杂度不相上下,并且它的实现更加简单。

跳跃表的使用场景

Redis 只在两个地方用到了跳跃表,一个是实现有序集合健,另一个是在集群节点中用做内部数据结构,除此之外,跳跃表在 Redis 里没有其它用途;

Redis使用跳跃表作为有序集合键(Zset)的底层实现之一,如果一个有序集合包含的元素数量比较多。又或者有序集合中的元素的成员是比较长的字符串时,Redis就会使用跳跃表来作为有序集合键的底层实现。

顺便提一嘴,Zset另外一种底层实现是压缩列表(ZipList)

常见使用于各种排行榜。例如某某游戏战力排行榜,他会统计所有玩家的战力,将Top100展示出来。那么就可以使用Zset完成。

Zset会接收两个参数:

  1. score分值,主要用于排序时大小顺序的依据。
  2. value值,具体要排序的名称

铛铛铛铛~,萧炎闪亮登场,下面给大家演示一下异火排行榜(部分)。 首先录入异火信息~

arduino复制代码// 给Zset添加异火:生灵之焱,战力66666
127.0.0.1:6379> zadd YHRanking 66666 "生灵之焱"  

127.0.0.1:6379> zadd YHRanking 55555 "八荒破灭焱"  

127.0.0.1:6379> zadd YHRanking 88888 "净莲妖火"  

127.0.0.1:6379> zadd YHRanking 77777 "金帝焚天炎"  

127.0.0.1:6379> zadd YHRanking 200000 "帝炎"  

127.0.0.1:6379> zadd YHRanking 99999 "虚无吞炎"  

127.0.0.1:6379> zadd YHRanking 22222 "三千焱炎火" 

127.0.0.1:6379> zadd YHRanking 20000 "九幽风炎"  

127.0.0.1:6379> zadd YHRanking 44444 "九幽金祖火"  

127.0.0.1:6379> zadd YHRanking 33333 "红莲业火"  

127.0.0.1:6379> zadd YHRanking 19999 "骨灵冷火"
127.0.0.1:6379>

下面展示异火威力排名排序

默认情况下按照分值从小到大排序 (从0开始排序,zrank 升序,zrevrank降序)

ruby复制代码127.0.0.1:6379> zrevrange YHRanking 0 -1
帝炎
虚无吞炎
净莲妖火
金帝焚天炎
生灵之焱
八荒破灭焱
九幽金祖火
红莲业火
三千焱炎火
九幽风炎
骨灵冷火

可以正着排,也可以反着排

ruby复制代码127.0.0.1:6379> zrange YHRanking 0 -1
骨灵冷火
九幽风炎
三千焱炎火
红莲业火
九幽金祖火
八荒破灭焱
生灵之焱
金帝焚天炎
净莲妖火
虚无吞炎
帝炎

TOP5

ruby复制代码127.0.0.1:6379> zrevrange YHRanking 0 4
帝炎
虚无吞炎
净莲妖火
金帝焚天炎
生灵之焱

可以查询骨灵冷火排名多少。

ruby复制代码127.0.0.1:6379> zrevrank YHRanking 帝炎
0
127.0.0.1:6379> zrevrank YHRanking 九幽风炎
9
127.0.0.1:6379> zrevrank YHRanking 骨灵冷火
10

还有很多功能,就不一一展示啦。

跳跃表的原理

查询策略

由于Zset需要支持随机的删除与插入,所以不适合使用数据结构。下面来看下若是使用有序的链表会怎样实现? 若是数组的查询可以使用二分查找法加快查找速度,而链表没有索引下标,查找值为9的元素则需要从头开始遍历 1,2,3,4,5,6,7,8,9 。 时间复杂度为O(n).

为了提高效率,可以在某些节点上加上多个指针,多加的指针指向跳过下一个节点之后的节点。

可能有掘友看不懂上图,我来说明一下,其中1,1这两个方块代表着同一个节点的两个指针,可以看到元素1的二层指针指向5的节点,元素1的一层指针指向2的节点。这样在查找9这个元素的时候,会从最高节点开始向后遍历,查到第一个比自己大的元素之前,然后来到下层,前往这层的后一个指针,知道再次查到第一个比自己大的元素之前,依然向下,直到到底最低层的指针,就能够找到查询的值。如图查找路径即为1,5,7,8,9。

定位插入点时,先在顶层进行定位,然后下潜到下一级定位,一直下潜到最底层,找到合适的位置,将新元素插进去。

数据结构

c++复制代码typedef struct zskiplistNode {  
//层  
struct zskiplistLevel {  
//前进指针  
struct zskiplistNode *forward;  
//跨度  
unsigned int span;  
}  
level[];  
//后退指针  
struct zskiplistNode *backward;  
//分值  
double score;  
//成员对象  
robj * obj;  
}  
zskiplistNode;

总结

跳跃表是有序集合的底层实现之一。

?Redis的跳跃表实现由zskiplist和zskiplistNode两个结构组成,其中zskiplist用于保存跳跃表信息(比如表头节点、表尾节点、长度),而zskiplistNode则用于表示跳跃表节点。

?每个跳跃表节点的层高都是1至32之间的随机数。

?在同一个跳跃表中,多个节点可以包含相同的分值,但每个节点的成员对象必须是唯一的。

?跳跃表中的节点按照分值大小进行排序,当分值相同时,节点按照成员对象的大小进行排序。

相关推荐

【推荐】一个开源免费、AI 驱动的智能数据管理系统,支持多数据库

如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!.前言在当今数据驱动的时代,高效、智能地管理数据已成为企业和个人不可或缺的能力。为了满足这一需求,我们推出了这款开...

Pure Storage推出统一数据管理云平台及新闪存阵列

PureStorage公司今日推出企业数据云(EnterpriseDataCloud),称其为组织在混合环境中存储、管理和使用数据方式的全面架构升级。该公司表示,EDC使组织能够在本地、云端和混...

对Java学习的10条建议(对java课程的建议)

不少Java的初学者一开始都是信心满满准备迎接挑战,但是经过一段时间的学习之后,多少都会碰到各种挫败,以下北风网就总结一些对于初学者非常有用的建议,希望能够给他们解决现实中的问题。Java编程的准备:...

SQLShift 重大更新:Oracle→PostgreSQL 存储过程转换功能上线!

官网:https://sqlshift.cn/6月,SQLShift迎来重大版本更新!作为国内首个支持Oracle->OceanBase存储过程智能转换的工具,SQLShift在过去一...

JDK21有没有什么稳定、简单又强势的特性?

佳未阿里云开发者2025年03月05日08:30浙江阿里妹导读这篇文章主要介绍了Java虚拟线程的发展及其在AJDK中的实现和优化。阅前声明:本文介绍的内容基于AJDK21.0.5[1]以及以上...

「松勤软件测试」网站总出现404 bug?总结8个原因,不信解决不了

在进行网站测试的时候,有没有碰到过网站崩溃,打不开,出现404错误等各种现象,如果你碰到了,那么恭喜你,你的网站出问题了,是什么原因导致网站出问题呢,根据松勤软件测试的总结如下:01数据库中的表空间不...

Java面试题及答案最全总结(2025版)

大家好,我是Java面试陪考员最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试题及答案。涉及的内容非常全面,包含:Spring、MySQL、JVM、Redis、Linux、Sprin...

数据库日常运维工作内容(数据库日常运维 工作内容)

#数据库日常运维工作包括哪些内容?#数据库日常运维工作是一个涵盖多个层面的综合性任务,以下是详细的分类和内容说明:一、数据库运维核心工作监控与告警性能监控:实时监控CPU、内存、I/O、连接数、锁等待...

分布式之系统底层原理(上)(底层分布式技术)

作者:allanpan,腾讯IEG高级后台工程师导言分布式事务是分布式系统必不可少的组成部分,基本上只要实现一个分布式系统就逃不开对分布式事务的支持。本文从分布式事务这个概念切入,尝试对分布式事务...

oracle 死锁了怎么办?kill 进程 直接上干货

1、查看死锁是否存在selectusername,lockwait,status,machine,programfromv$sessionwheresidin(selectsession...

SpringBoot 各种分页查询方式详解(全网最全)

一、分页查询基础概念与原理1.1什么是分页查询分页查询是指将大量数据分割成多个小块(页)进行展示的技术,它是现代Web应用中必不可少的功能。想象一下你去图书馆找书,如果所有书都堆在一张桌子上,你很难...

《战场兄弟》全事件攻略 一般事件合同事件红装及隐藏职业攻略

《战场兄弟》全事件攻略,一般事件合同事件红装及隐藏职业攻略。《战场兄弟》事件奖励,事件条件。《战场兄弟》是OverhypeStudios制作发行的一款由xcom和桌游为灵感来源,以中世纪、低魔奇幻为...

LoadRunner(loadrunner录制不到脚本)

一、核心组件与工作流程LoadRunner性能测试工具-并发测试-正版软件下载-使用教程-价格-官方代理商的架构围绕三大核心组件构建,形成完整测试闭环:VirtualUserGenerator(...

Redis数据类型介绍(redis 数据类型)

介绍Redis支持五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)及Zset(sortedset:有序集合)。1、字符串类型概述1.1、数据类型Redis支持...

RMAN备份监控及优化总结(rman备份原理)

今天主要介绍一下如何对RMAN备份监控及优化,这里就不讲rman备份的一些原理了,仅供参考。一、监控RMAN备份1、确定备份源与备份设备的最大速度从磁盘读的速度和磁带写的带度、备份的速度不可能超出这两...

取消回复欢迎 发表评论: