16 zset 相关操作

2024-05-28 15:18
文章标签 16 操作 相关 zset

本文主要是介绍16 zset 相关操作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

相关介绍主要围绕着如下的一些常用的命令, 来看看 zset 相关操作的具体 api 

如下常用的命令来自于我们常见的教程 : https://www.runoob.com/redis/redis-sorted-sets.html 

本文的相关代码 拷贝自 redis-6.2.0  

代码来自于 https://redis.io/ 
 

数据结构

当 zset 中的元素数量小于等于 zset_max_ziplist_entries(默认为 128), 并且每一个元素长度都小于等于 zset_max_ziplist_value(默认为 64) 的时候, 是基于 ziplist 来存储数据 

否则是基于 skiplist 来存储数据 

ZADD key score1 member1 [score2 member2]

这里可以看出的是 参数的数量要求大于等于 4 个, 可以传递 多个 score, member 对  

我们来看一下 zaddCommand 

搜显示 校验客户端输入的 options, 存储到 flags 里面, 接着 从 flags 中提取上下文所需要的标记到标记变量 

校验 score, member 是否是成对出现, 各个 flag 是否存在冲突的标记 

解析各个 score 数组, 确保格式正确 

如果 zset 不存在, 则创建给定的 zset, 并初始化到 db->dict 里面 

然后循环 score, member 对, 循环添加 score -> member 

返回给客户端 添加的元素的数量 

zset 中添加元素的具体的方式 

如果是 ziplist 的编码方式, 查询 ele 在 zset 中是否存在, 如果存在, 判断当前 score 和 newscore 是否满足 lt/gt 约束[确保 newscore 小于/大于 score], 先从 ziplist 中删除已有的 ele, score, 在新增 ele, newscore[新增元素按照score排序] 

    如果 zset 中不存在 ele, 则新增 ele, newscore 到 zset 里面 [新增元素按照score排序]  

如果是 skiplist 的编码方式, 直接基于 skiplist 的 api 来进行操作 

最终客户端这边展示的结果如下, zset 不存在, 符合 ziplist 的条件, 创建了基于一个 ziplist 的 zset, 最终添加了 三个元素 

ZCARD key - 执行 zcard zset

这里可以看出的是 参数的数量要求等于 2 个 

我们来看一下 zcardCommand 

获取 key 对应的 entry, 确保类型为 zset 

返回 value 中存储的元素的数量 

zsetLength 的具体实现如下, 获取的是 zset 里面的 score, member对 的数量 

最终客户端这边展示的结果如下, zset 中存在 [(60 -> chinese), (70 -> match), (80 -> english)], 总共是三个元素 

ZCOUNT key min max - 执行 zcount zset 60 70 

这里可以看出的是 参数的数量要求等于 4 个 

我们来看一下 zcountCommand 

获取 key 对应的 entry, 确保类型为 zset 

获取 min, max, 并确保类型正确 

如果是以 ziplist 编码, 找到第一个在 range 的元素, 如果没有 返回 0, 否则迭代元素 直到不再 range, 返回元素的数量 

如果是以 skiplist 编码, 找到第一个在 range 的元素, 如果没有 返回 0, 否则迭代元素 直到不再 range, 返回元素的数量 

最终客户端这边展示的结果如下, zset 中存在 [(60 -> chinese), (70 -> match), (80 -> english)], score 在 [60, 70] 区间的元素总共有两个 

ZINCRBY key increment member - 执行 zincry zset 20 chinese

这里可以看出的是 参数的数量要求等于 4 个 

zincrbyCommand 的实现是基于 zaddGenericCommand 来实现的, 请参见上面的 zadd 

最终客户端这边展示的结果如下, zset 中存在 [(60 -> chinese), (70 -> match), (80 -> english)], 我们给 chinese 增加了 20, chinese 的 score 为 80, 这里返回的即为 newscore 

ZINTERSTORE destination numkyes key [key] 

暂时先放在这里 

ZUNIONSTORE destinations numkeys key [key]

暂时先放在这里 

ZLEXCOUNT key min max - 执行 zlexcount zset [c [e

这里可以看出的是 参数的数量要求等于 4 个 

我们来看一下 zlexcountCommand 

获取 key 对应的 entry, 确保类型为 zset 

获取 min, max, 并确保类型正确 

不管编码是 ziplist, skiplist 找到 min 所在的元素, 然后向后迭代 直到走出 (min, max) 区间[闭, 包取决于客户输入], 统计元素的数量 

注意 : 所有的 member 正序的情况下才有意义[规范上面限定的是 所有的 score 都相同的场景] 

zlexcount 文档上面的限定, 在所有的元素的 score 都相同的情况下使用, 查询语义上 在 min, max 区间的元素数量 

最终客户端这边展示的结果如下, zset 中存在 [(80 -> chinese), (70 -> match), (80 -> english)]

我们给 match 增加了 10, match 的 score 为 80 

此时 我们的几个元素 score 均相同, (socre, memeber) 默认是按照 member 字典序来进行的排序 

此时统计 大于等于 'c', 小于等于 'e' 的元素只有 "chinese" 一个 

此时统计 大于等于 'c', 小于等于 'f' 的元素只有 "chinese", "english" 两个 

ZRANGE key start stop [WITHSCORES] - 执行 zrange zset 60 70 

这里可以看出的是 参数的数量要求大于等于 4 个 

zrange, zrangeByLex, zrangeByScore, zRevRange, zRevRangeByLex, zRevRangeByScore 都是差不多, 这里只介绍一个 

我们来看一下 zrangeCommand 

解析参数 offset, limit, byScore, byLex, rev, withScores 等等 

根据 byRank/byScore/byOffset 分别将 min, max 解析到 (opt_start, opt_end), range, lexRange 里面 

获取 key 对应的 entry, 确保类型为 zset 

根据 byRank/byScore/byOffset 各自不同的实现来不同的处理 

byRank 的处理方式如下 

无论是 ziplist, 还是 skiplist, 其处理方式都是 现根据 start 获取第一个元素, 然后迭代 (end-start+1) 个元素 

byScore 的处理方式如下

无论是 ziplist, 还是 skiplist, 其处理方式都是 找到区间的第一个元素, 然后向前/后迭代直到迭代出 range 

byLex 和 byScore 实现方式类似, 这里不再赘述 

仅仅在 member 正序排列的时候有意义 

最终客户端这边展示的结果如下, zset 中存在 [(60 -> chinese), (70 -> match), (80 -> english)] 

然后 score 在 60, 70 区间的元素有 chinese, match 两个元素 

ZRANK key member - 执行 zrank zset match 

这里可以看出的是 参数的数量要求等于 3 个 

zrank, zrevrank 都是差不多, 这里只介绍一个 

我们来看一下 zrankCommand 

获取给定的元素的 排名 

无论是 ziplist 还是 quicklist, 来寻找 rank 都很简单 

最终客户端这边展示的结果如下, zset 中存在 [(60 -> chinese), (70 -> match), (80 -> english)], 我们查询的 match 顺序上来说是 第二位 

ZREM key member1 [member2] - 执行 zrem zset match 

这里可以看出的是 参数的数量要求大于等于 3 个 

我们来看一下 zremCommand 

获取 key 对应的 entry, 确保类型为 zset 

遍历 memberList 逐个删除 member, 如果最终集合元素删除光了, 移除 key 对应的 entry 

如果删除了 member, 更新 dirty, 发送 更新通知 

返回给客户端 删除的 member 的数量 

最终客户端这边展示的结果如下, zset 中存在 [(60 -> chinese), (70 -> match), (80 -> english)], 我们删除了 match, 服务端返回的是删除元素的数量, 删除了一个元素 

ZREMRANGEBYSCORE key min max - 执行 zremrangebyscore zset 0 30

这里可以看出的是 参数的数量要求等于 4 个 

zremrangebyscore, zremrangebylex, zremrangebyrank 都是差不多, 这里只介绍一个 

我们来看一下 zremRangeByScoreCommand 

和上面 zcount 的实现差不多, 首先是确认类型, 解析参数, 根据 byRank/byScore/byOffset 分别将 min, max 解析到 (start, end), range, lexRange 里面 

然后根据 range 来移除元素 

如果删除了元素, 更新 dirty, 发送 更新通知 

返回给客户端 删除的 member 的数量 

最终客户端这边展示的结果如下, zset 中存在 [(60 -> chinese), (80 -> english)], 我们删除的区间是 [0, 30] 不会删除任何元素 

ZSCORE key member - 执行 zscore zset chinese 

这里可以看出的是 参数的数量要求等于 3 个 

我们来看一下 zscoreCommand 

获取 key 对应的 entry, 确保类型为 zset 

根据元素 获取 score 

根据元素获取 score 

根据 ziplist, skiplist 不同的方式查询 member 对应的 entry 

填充对应的 score 到接受的对象上 

最终客户端这边展示的结果如下, zset 中存在 [(60 -> chinese), (80 -> english)], chinese 对应的 score 为 60 

ZSCAN key cursor [MATCH pattern] [COUNT count] - 执行 zscan zset 0 COUNT 1

这里可以看出的是 参数的数量要求大于等于 3 个 

zscan 这里同样是使用的 scanGenericCommand 

这的迭代类似于 11 key 相关操作 

不过对于这里编码为 ziplist 的情况 COUNT 这两个选项是没用的[这是一个很细的细节] 

迭代的是 zset 里面的所有的元素  

如果编码是 skiplist, zscan 是基于维护的一个额外的 dict 来进行 scan 的[这也是一个很细的细节] 

这篇关于16 zset 相关操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1010930

相关文章

使用MongoDB进行数据存储的操作流程

《使用MongoDB进行数据存储的操作流程》在现代应用开发中,数据存储是一个至关重要的部分,随着数据量的增大和复杂性的增加,传统的关系型数据库有时难以应对高并发和大数据量的处理需求,MongoDB作为... 目录什么是MongoDB?MongoDB的优势使用MongoDB进行数据存储1. 安装MongoDB

Linux使用fdisk进行磁盘的相关操作

《Linux使用fdisk进行磁盘的相关操作》fdisk命令是Linux中用于管理磁盘分区的强大文本实用程序,这篇文章主要为大家详细介绍了如何使用fdisk进行磁盘的相关操作,需要的可以了解下... 目录简介基本语法示例用法列出所有分区查看指定磁盘的区分管理指定的磁盘进入交互式模式创建一个新的分区删除一个存

Golang操作DuckDB实战案例分享

《Golang操作DuckDB实战案例分享》DuckDB是一个嵌入式SQL数据库引擎,它与众所周知的SQLite非常相似,但它是为olap风格的工作负载设计的,DuckDB支持各种数据类型和SQL特性... 目录DuckDB的主要优点环境准备初始化表和数据查询单行或多行错误处理和事务完整代码最后总结Duck

关于Maven生命周期相关命令演示

《关于Maven生命周期相关命令演示》Maven的生命周期分为Clean、Default和Site三个主要阶段,每个阶段包含多个关键步骤,如清理、编译、测试、打包等,通过执行相应的Maven命令,可以... 目录1. Maven 生命周期概述1.1 Clean Lifecycle1.2 Default Li

C# 读写ini文件操作实现

《C#读写ini文件操作实现》本文主要介绍了C#读写ini文件操作实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录一、INI文件结构二、读取INI文件中的数据在C#应用程序中,常将INI文件作为配置文件,用于存储应用程序的

numpy求解线性代数相关问题

《numpy求解线性代数相关问题》本文主要介绍了numpy求解线性代数相关问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 在numpy中有numpy.array类型和numpy.mat类型,前者是数组类型,后者是矩阵类型。数组

Python使用qrcode库实现生成二维码的操作指南

《Python使用qrcode库实现生成二维码的操作指南》二维码是一种广泛使用的二维条码,因其高效的数据存储能力和易于扫描的特点,广泛应用于支付、身份验证、营销推广等领域,Pythonqrcode库是... 目录一、安装 python qrcode 库二、基本使用方法1. 生成简单二维码2. 生成带 Log

Java操作ElasticSearch的实例详解

《Java操作ElasticSearch的实例详解》Elasticsearch是一个分布式的搜索和分析引擎,广泛用于全文搜索、日志分析等场景,本文将介绍如何在Java应用中使用Elastics... 目录简介环境准备1. 安装 Elasticsearch2. 添加依赖连接 Elasticsearch1. 创

java Stream操作转换方法

《javaStream操作转换方法》文章总结了Java8中流(Stream)API的多种常用方法,包括创建流、过滤、遍历、分组、排序、去重、查找、匹配、转换、归约、打印日志、最大最小值、统计、连接、... 目录流创建1、list 转 map2、filter()过滤3、foreach遍历4、groupingB

Java操作PDF文件实现签订电子合同详细教程

《Java操作PDF文件实现签订电子合同详细教程》:本文主要介绍如何在PDF中加入电子签章与电子签名的过程,包括编写Word文件、生成PDF、为PDF格式做表单、为表单赋值、生成文档以及上传到OB... 目录前言:先看效果:1.编写word文件1.2然后生成PDF格式进行保存1.3我这里是将文件保存到本地后