广告
返回顶部
首页 > 资讯 > 数据库 >Redis中ZSet的具体使用
  • 516
分享到

Redis中ZSet的具体使用

RedisZSet使用 2022-07-18 11:07:09 516人浏览 泡泡鱼
摘要

目录一、题目二、ZSet 简单使用三、ZSet 结构四、跳跃表五、场景案例一、题目 ZSet能用在哪些场景?跳表查找的过程,时间复杂度 二、ZSet 简单使用 举个例子,fruit-price 是一个有序集合键,这个有序

一、题目

ZSet能用在哪些场景?跳表查找的过程,时间复杂度

二、ZSet 简单使用

举个例子,fruit-price 是一个有序集合键,这个有序集合以水果名为成员,水果价钱为分值,保存了 130 款水果的价钱:

Redis>ZADD fruit-price 5 "banana"
redis>ZADD fruit-price 6.5 "cherry"
redis>ZADD fruit-price 8 "apple"


redis> ZRANGE fruit-price 0 2 WITHSCORES
1) "banana"
2) "5"
3) "cherry"
4) 6.5
5) "apple"
6) "8"

redis> ZCARD fruit-price
(integer)130

三、ZSet 结构

ZSet 结构即支持单个元素查询,又支持范围查询,是如何实现的呢?

Redis 中有两种数据结构来支持 ZSet 的功能,一个是字典 dict ,一个是 zskipList; 字典保存着从 member 到 score 的映射,跳跃表按 score 从小到大保存所有集合元素

先看下 ZSet 在代码中的定义:

typedef struct zset {
   dict *dict;
   zskiplist *zsl;
} zset;

dict 各种编程语言中都有实现。可以保证 O(1) 的时间复杂度; 我们继续看 zskiplist 的定义:

typedef struct zskiplist {
   struct zskiplistnode *header, *tail;
   unsigned long length;
   int level;
} zskiplist;

zskiplist 是 Redis 对 skiplist 做了变种,skiplist 就是我们常说的跳表;

四、跳跃表

跳跃表的特点

  • 由许多层结构组成,每层都是一个有序链表
  • 最底层的链表包含所有元素
  • 如果一个元素出现在 level i 层的链表中,则它在 level i 之下的链表中也都会出现
  • 每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素

查找过程

  • 跳表的查找会从顶层链表的头部元素开始遍历该链表,直到找到元素大于或等于目标元素的节点,如果当前元素正好等于目标,那么就直接返回它;
  • 如果当前元素大于目标或到达链表尾部,则移动到前一个节点的位置,然后垂直下降到下一层;
  • 正因为 Skiplist 的搜索过程会不断地从一层跳跃到下一层的,所以被称为跳跃表;

举例说明

假设链接包含 1-10,共 10 个元素。我们要找到第 9 个,需要从 header 遍历,共 9 次才能找到:

在这里插入图片描述

一次只能比较一个数,最坏的情况下时间复杂度是 O(n),如果我们一次可以比较 2 个元素就好了:

在这里插入图片描述

一次查找 2 个的话,我们只找了 5 次就找到了。所以就有了类似下面的结构,在链表上增加一层减少了元素个数的 “链表”:

在这里插入图片描述

如果增加两层 “链表”,只查找 3 次就可以找到:

在这里插入图片描述

即便是我们找元素 8,也只需要遍历 1 -> 4 -> 7 -> 8,共 4 次查询;

这样查找过程就非常类似于一个二分查找,使得查找的时间复杂度可以降低到 O(log n)

ZskipList 插入过程:

在这里插入图片描述

从上面 Skiplist 的创建和插入过程可以看出,每一个节点的层数(level)是随机出来的,而且新插入一个节点不会影响其它节点的层数。 因此,插入操作只需要修改插入节点前后的指针,而不需要对很多节点都进行调整。这就降低了插入操作的复杂度

Redis 初始化的时候,只判断存储的元素长度是否大于 64 个字节。大于 64 个字节选择 Zkiplist,否则 Ziplist。当执行增删改查的方法,根据是 ziplist 还是 zkiplist 选择不同的实现。只需要记住 zset,在两种情况下使用 ziplist:

保存的元素个数不足 128 个;单个元素的大小超过 64 byte;

ziplist 编码的有序集合使用紧挨在一起的压缩列表节点来保存,第一个节点保存 member,第二个保存 score。ziplist 内的集合元素按 score 从小到大排序,score 较小的排在表头位置

为什么采用跳跃表

  • 跳表就是这样的一种数据结构,结点是跳过一部分的,从而加快了查询的速度。类似于 HashMap 中,Java 8 中当哈希冲突个数大于 7 个的时候,转换为红黑树;
  • 跳表跟红黑树两者的算法复杂度差不多,为什么 Redis 要使用跳表而不使用红黑树呢?跳表相对于红黑树,代码简单;
  • 如果我们要查询一个区间里面的值,用平衡树实现可能会麻烦。删除一段区间时,如果是平衡树,就会相当困难,毕竟涉及到树的平衡问题,而跳表则没有这种烦恼;

五、场景案例

1、信息统计

假设我们有某个班级所有学生的语文成绩,想统计、查询区间范围、查询单个学生成绩、满足高性能读取这些需求, Redis 的 zset 结构无疑是最好的选择。Redis 提供了丰富的 api。示例

ZADD yuwen 90 s01 89 s03 99 s02 74 s04 97 s05

以 yuwen 为 key 分别存储了 s01 到 s06 共计 6 名学生的分数,我们可以查询任一学生的成绩:

ZSCORE yuwen s03

可以按照排序返回指定区间内的所有元素

ZRANGE yuwen 1 2 withscores

可以访问指定分数区间内的所有元素

ZRANGEBYSCORE yuwen 90 100 withscores

可以统计指定区间内的个数

ZCOUNT yuwen 80 90

2、排行榜

  • 经常浏览技术社区的话,应该对 “1小时最热门” 这类榜单不陌生。如何实现呢?如果记录在数据库中,不太容易对实时统计数据做区分;
  • 我们以当前小时的时间戳作为 zset 的 key,把贴子 ID 作为 member ,点击数评论数等作为 score,当 score 发生变化时更新 score;
  • 利用 ZREVRANGE 或者 ZRANGE 查到对应数量的记录;

到此这篇关于Redis中ZSet的具体使用的文章就介绍到这了,更多相关Redis ZSet使用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

您可能感兴趣的文档:

--结束END--

本文标题: Redis中ZSet的具体使用

本文链接: https://www.lsjlt.com/news/33386.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Redis中ZSet的具体使用
    目录一、题目二、ZSet 简单使用三、ZSet 结构四、跳跃表五、场景案例一、题目 ZSet能用在哪些场景?跳表查找的过程,时间复杂度 二、ZSet 简单使用 举个例子,fruit-price 是一个有序集合键,这个有序...
    99+
    2022-07-18
    RedisZSet使用
  • redis中zset如何使用
    这篇文章将为大家详细讲解有关redis中zset如何使用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Redis中zset是set的一个升级版本,他在set的基础上增加了...
    99+
    2022-10-18
  • Yii redis zset有序集合的使用
      和散列存储着键与值之间的映射关系类似,有序集合也存储着成员与分值之间的映射,并且提供了分值处理命令,以及根据分值大小有序地获取(fetch)和扫描(scan)成员和分值的命令。这里介绍一些常用命令,以及在 Yii 中的使用。 ...
    99+
    2015-07-18
    Yii redis zset有序集合的使用
  • Redis可视化工具Redis Desktop Manager的具体使用
    项目中用到了redis,想查询redis中的数据,一直想找一个可视化工具,今天发现了Redis Desktop Manager,试用了一下,很好用。 1.下载 Redis Des...
    99+
    2022-11-12
  • Redis之sql缓存的具体使用
    目录1.环境搭建2.Redis配置3.功能实现4.缓存注解的使用说明1.环境搭建 <!-- RedisTemplate --> <dependency>...
    99+
    2022-11-12
  • SpringBoot使用Redis的zset统计在线用户信息
    目录在线用户统计的实现 基于数据库实现 基于Redis实现 Redis的Zset Zset的部分操作 一个示例 在线用户服务的实现 实现思路 使用示例内存消耗分析 最后 统计在线用户...
    99+
    2022-11-12
  • Redis怎么使用ZSET实现消息队列
    这篇文章主要介绍了Redis怎么使用ZSET实现消息队列的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Redis怎么使用ZSET实现消息队列文章都会有所收获,下面我们一起来看看吧。1.redis 用zset做消...
    99+
    2023-07-05
  • Redis使用ZSET实现消息队列使用小结
    目录1.Redis 用zset做消息队列如何处理消息积压2.redis分片并使用zset做消息队列3. redis如何分片4. redis使用Java发送消息到zset队列并对消息进行分片处理5. redis使用zset...
    99+
    2023-03-19
    Redis使用ZSET实现消息队列 Redis消息队列
  • Redis 整数集合的具体使用(intset)
    目录一、集合概述二、Redis 整数集合(intset)1、intset 结构定义2、编码方式3、编码升级三、整数集合常用操作1、创建集合2、元素设置3、元素获取 4、元素...
    99+
    2022-11-13
  • Redis三种特殊数据类型的具体使用
    目录一、HyperLogLog 基数统计1.1 什么是基数?1.2 使用基数统计的好处1.3 应用场景1.4 注意事项 1.5 基本命令1.6 使用二、Geospatial...
    99+
    2022-11-13
  • Redis 配置文件重要属性的具体使用
    1. UNITS 单位 # 1k => 1000 bytes # 1kb => 1024 bytes # 1m => 1000000 bytes # 1mb ...
    99+
    2022-11-12
  • SpringBoot Redis 发布订阅模式(Pub/Sub)的具体使用
    目录Redis命令行下使用发布订阅 publish 发布 subscribe 订阅 SpringBoot中使用Redis的发布订阅功能 发布者 订阅者 消息监听容器 注意:redis...
    99+
    2022-11-12
  • django中websocket的具体使用
    websocket是一种持久化的协议,HTTP协议是一种无状态的协议,在特定场合我们需要使用长连接,做数据的实时更新,这种情况下我们就可以使用websocket做持久连接。http与...
    99+
    2022-11-13
  • Python中collections.Counter()的具体使用
    目录Counter类创建计数值的访问与缺失的键计数器的更新键的删除elements()most_common([n])fromkeys浅拷贝copy算术和集合操作常用操作Counter类 Counter类的目的是用...
    99+
    2022-06-02
    Python collections.Counter()
  • pandas中df.rename()的具体使用
    df.rename()用于更改行列的标签,即行列的索引。可以传入一个字典或者一个函数。在数据预处理中,比较常用。 官方文档: DataFrame.rename(self, mappe...
    99+
    2022-11-11
  • numpy中nan_to_num的具体使用
    在Numpy中NaN值一般出现在数据清洗前,出现这个值说明这个数据是缺失的 在有些时候我们会选择直接删除这些数据,但有些时候这些数据是不能删除的,这个时候我们就需要使用一些方法将np...
    99+
    2022-11-11
  • React中useRef的具体使用
    相信有过React使用经验的人对ref都会熟悉,它可以用来获取组件实例对象或者是DOM对象。 而useRef这个hooks函数,除了传统的用法之外,它还可以“跨渲染周期”保存数据。 ...
    99+
    2022-11-12
  • python中pywifi的具体使用
    目录写在前面pywifi常量接口wifi连接代码写在前面 无线AP(Access Point):即无线接入点 python的wifi管理模块叫pywifi 安装 pip instal...
    99+
    2023-03-06
    python pywifi
  • java中Thread.sleep()的具体使用
    目录sleep功能介绍:sleep Thread.sleep()被用来暂停当前线程的执行,会通知线程调度器把当前线程在指定的时间周期内置为wait状态。当wait时间结束,线程状态重...
    99+
    2023-05-17
    java Thread.sleep
  • Golang中Model的具体使用
    目录导语使用之前的准备开始使用发布版本引用自己封装的包修改版本导语 我们都知道在Golang中我们一般都是设置GOPATH目录,这个目录主要存放我们的第三方包,这个方式一直不是很方便...
    99+
    2023-05-14
    Golang Model使用 Golang Model
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作