对 Redis 中的有序集合SortedSet的理解

本篇说一下Redis中的 有序集合类型,曾几何时,我们想把所有数据存到内存中的 数据结构 中,但为了多机器共享内存,不得不将这块内存包装成wcf单独部署,同时还要考虑怎么序列化,烦心事太多太多。。。后来才知道有redis这么????????的东西,能把高级的,低级的数据结构单独包装到一个共享内存中。

一:有序集合(SortedSet)

可能有些初次接触SortedSet集合的朋友可能会说,这个集合的使用场景都有哪些???我可以明确的告诉你:范围查找 的天敌就是有序集合,任何大数据量下,查找一个范围的时间复杂度永远都是 O[(LogN)+M],其中M:返回的元素个数,为了从易到难,我们还是先看一下redis手册,挑选几个我们常用的方法观摩观摩效果。

从上面的17个命令中,毫无疑问,常用的命令为ZADD,ZREM,ZRANGEBYSCORE,ZRANGE。

1. ZADD


ZADD key score member [[score member] [score member] ...]
将一个或多个 member 元素及其 score 值加入到有序集 key 当中。

这个是官方的解释,赋值方式和hashtable差不多,只不过这里的key是有序的而已。下面我举个例子:我有一个fruits集合,其中记录了每个水果的price,然后我根据price的各种操作来获取对应的水果信息。

有了上面的基本信息,接下来我逐一送他们到SortedSet中,如下图:

从上面的图中,不知道你有没有发现到什么异常???至少有两种。

  • 浮点数近似值的问题,比如grape,我在add的时候,写明的是2.8,在redis中却给我显示近似值2.79999....,这个没关系,本来就是这样。

  • 默认情况下,SortedSet是以key的升序排序的方式进行存放。

2.  ZRANGE,ZREVRANGE


ZRANGE key start stop [WITHSCORES]返回有序集 key 中,指定区间内的成员。其中成员的位置按 score 值递增(从小到大)来排序。

上面就是ZRange的格式模版,前面我在说ZAdd的时候其实我也已经说了,但是这个不是重点,在说ZAdd的时候留下了一个问题就是ZRange,默认是按照key升序排序的, 对吧,那如果你想倒序显示的话,怎么办呢???其实你可以使用ZRange的镜像方法ZREVRANGE 即可,如下图:

3. ZRANGEBYSCORE


ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。

这个算是对SortedSet来说最最重要的方法了,文章开头我也说了,有序集合最利于范围查找,既然是查找,你得有条件对吧,下面我举个例子:

  • 我要找到1-4块钱的水果种类,理所当然,我会找到 葡萄,苹果,如下图:


127.0.0.1:6379> zrangebyscore fruits 1 4  withscores
1) "grape"
2) "2.7999999999999998"
3) "apple"
4) "3.5"
127.0.0.1:6379> 
  • 我要找到1-4区间中最接近4块的水果是哪个???这个问题就是要找到apple这个选项,那如果找到呢???仔细想想我可以这么做,将1-4区间中的所有数倒序再取第一条数据即可,对吧,如下代码。


127.0.0.1:6379> zrevrangebyscore fruits 4 1 withscores
1) "apple"
2) "3.5"
3) "grape"
4) "2.7999999999999998"
127.0.0.1:6379> zrevrangebyscore fruits 4 1 withscores limit 0 1
1) "apple"
2) "3.5"
127.0.0.1:6379> 

4. ZREM


ZREM key member [member ...]移除有序集 key 中的一个或多个成员,不存在的成员将被忽略。当 key 存在但不是有序集类型时,返回一个错误。

跟其他方法一样,zrem的目的就是删除指定的value成员,比如这里我要删除scores=3.5 的 apple记录。


127.0.0.1:6379> zrem fruits apple
(integer) 1
127.0.0.1:6379> zrange fruits 0 -1 withscores
1) "grape"
2) "2.7999999999999998"
3) "pear"
4) "4.0999999999999996"
5) "banana"
6) "5"
7) "nut"
8) "9.1999999999999993"
127.0.0.1:6379>

你会发现,已经没有apple的相关记录了,因为已经被我删除啦。。。

二:探索原理

简单的操作都已经演示完毕了,接下来探讨下sortedset到底是由什么数据结构支撑的,大家应该早有耳闻,sortedset在CURD的摊还分析上都是Log(N)的复杂度,可以与平衡二叉树媲美,它就是1987年才出来的新型高效数据结构跳跃表(SkipList),SkipList牛逼的地方在于跳出了树模型的思维,用多层链表的模式构造了Log(N)的时间复杂度,层的高度增加与否,采用随机数的模式,这个和 Treap树 的思想一样,用它来保持或者链表的平衡。

详细的我就不说了哈,不然的话又是一篇文章啦,如果非要了解的话,大家可以参见一下百度百科:http://baike.baidu.com/link?url=I8F7T W933ZjIeBea_-dW9KeNsfKXMni0IdwNB10N1qnVfrOh_ubzcUpgwNVgRPFw3iCkhewGaYjM_o51xchS8a

我大概看了下百科里面画的这张图,就像下面这样:

这幅图中有三条链,对吧,在SkipList中是必须要保证每条链中的数据必须有序才可以,这是必须的。

  • 如果要在level1层中找到节点6,那么你需要逐一遍历,需要6次查找才能正确的找到数据。

  • 如果你在level2层中找到节点6的话,那么你需要4次才能找到。

  • 如果你在level3层中找到节点6的话,那么你需要3次就可以找到。。。。

现在宏观理解上,是不是有一种感觉,如果level的层数越高,相对找到数据需要遍历的次数就越少,对吧,这就是跳跃表的思想,不然怎么跳哈,接下来我们来看看redis中是怎么定义这个skiplist的,它的源码在redis.h 中:


/* ZSETs use a specialized version of Skiplists */
typedef struct zskiplistNode {robj *obj;double score;struct zskiplistNode *backward;struct zskiplistLevel {struct zskiplistNode *forward;unsigned int span;} level[];
} zskiplistNode;typedef struct zskiplist {struct zskiplistNode *header, *tail;unsigned long length;int level;
} zskiplist;

从源码中可以看出如下几点:

  • zskiplistnode就是skiplist中的node节点,节点中有一个level[]数组,如果你够聪明的话,你应该知道这个level[]就是存放着上图中的 level1,level2,level3 这三条链。

  • level[]里面是zskiplistLevel实体,这个实体中有一个 *forward指针,这个指针就是指向同层中的后续节点。

  • 在zskiplistLevel中还有一个 robj类型的*obj指针,这个就是RedisObject对象哈,里面存放的就是我们的value值,接下来还有一个score属性,这个就是key值啦。。。skiplist就是根据它来进行排序的哈。

  • 接下来就是第二个枚举zskiplist,这个没什么意思,纯粹的包装层,比如里面的length是记录skiplist中的节点个数,level记录skiplist当前的层数,用*header,*tail 记录 skiplist 中的首节点和尾节点。。。仅此而已。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/306125.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php查询类似abab,ABAB中的正则表达式匹配编号(必须相同) - php

我已经搜索了许多答案来匹配ABAB pattern,这些答案与1212或2323的任意字符匹配,已阅读this too但我发现匹配ABAB模式的模式不起作用,它也匹配4444我试图找出模式来匹配以下主题:232345459898但可能不匹配4444或5555,因…

代码质量在「内卷时代」的重要性

这里是Z哥的个人公众号每周五11:45 按时送达当然了,也会时不时加个餐~我的第「173」篇原创敬上大家好,我是Z哥。提到代码质量,不知道你的脑海中浮现出的第一个词是什么?规范?可读性?…

oracle asm 配置失败,Oracle ASMLib安装与配置

什么是ORACLE ASMLib?ASMLib 是一个适用于 Oracle 数据库 的自动存储管理(ASM)功能的支持库。ASM简化了数据库和管理,它不再需要 DBA 直接管理可能数千个的 Oracle 数据库文件,而只需管理分配给 Oracle 数据库的磁盘组。ASMLib 令使用 ASM 的…

.NET Core AWS S3云存储

【导读】最近有需要用到AWS S3云存储上传附件,这里对利用.NET或.NET Core在调用SDK APi需要注意的一点小问题做个记录,或许能对后续有用到的童鞋提供一点帮助Amazon Simple Storage Service (Amazon S3) 是一种对象存储服务,提供行业领先的可…

oracle数据库查看size,[oracle] 查看oracle数据库表空间使用率,定位数据size较大对象...

1.查看表空间使用情况with ts as (SELECT d.tablespace_name "Name", d.status "Status",TO_CHAR (NVL (a.MAXBYTES / 1024 / 1024 /1024, 0), 99,999,990.90) "Maxsize (G)",TO_CHAR (NVL (a.BYTES / 1024 / 1024 /1024, 0), 99,999,990.90) &q…

如何解决在ASP.NET Core中找不到图像时设置默认图像

背景web上如果图片不存在一般是打xx,这时候一般都是会设置默认的图片代替。现在用中间件的方式实现统一设置, 一次设置,全部作用 。此示例演示如何解决在ASP.NET Core中找不到图像时设置默认图像先决条件Visual Studio 2017或更高版本。启用V…

缩减oracle日志,[20180829]减少日志生成量.txt

[20180829]减少日志生成量.txt--//最近一段时间优化一下生产数据库,主要是问题比我预计要严重,实际上exadata实在太快了,把许多问题都给掩盖了.--//实际上这个问题很早就存在,我实在不想提,基于国内许多应用都可能存在类似问题,还是写一下.SQL ordered by Executions%CPU - CPU…

ACM中算法时间约束

ACM中算法时间约束 一般ACM竞赛C/C的时间限制是一秒,因此可以根据题目数据来推断该题所使用的算法。 算法的时间复杂度在 1 0 7 10^7 107左右合适,最多不能超过 1 0 8 10^8 108, O ( n ) O(n) O(n)的极限就在 1 0 8 10^8 108左右。 问题规…

MiniProfiler,一个.NET简单但有效的微型分析器

背景MVC MiniProfiler是Stack Overflow团队设计的一款对ASP.NET MVC的性能分析的小程序。可以对一个页面本身,及该页面通过直接引用、Ajax、Iframe形式访问的其它页面进行监控,监控内容包括数据库内容,并可以显示数据库访问的SQL(支持EF、EF …

oracle类似isempty,NULLs和empty strings在不同数据库的中特点

1.以oracle为例SQL> create table test(id int primary key,content varchar(20));SQL> INSERT INTO test (id, content) VALUES (1, NULL);SQL> INSERT INTO test (id, content) VALUES (2, );SQL> INSERT INTO test (id, content) VALUES (3, );SQL> INSERT …

龙芯.NET正式发布 稳步推进生态建设

2020年12月19日,2020中国. NET开发者大会于苏州开幕。此次大会上,龙芯发布了龙芯.NET 3。龙芯.NET 3基于.NET Core 3.1,支持该版本具备的所有主要功能,包括GC、AOT等。CoreCLR、CoreFX、ASP.NET Core等库的测试通过情况与x64/arm6…

有温度的技术,改善上亿人的生活

06有温度的技术,改善上亿人的生活鱼小皮哥,现在的 APP 真是越来越难用了,功能多、操作复杂、广告更多。唉,可不是么,而且人们的生活已经离不开 APP 了!老百鱼小皮我爷爷最近的视力下降的很快,用…

Linux链接文件包括,Linux操作系统——系统各目录有什么作用、以及文件链接过程...

三、 Linux 系统目录结构/bin — 用来贮存用户命令。目录 /usr/bin 也被用来贮存用户命令。/sbin — 许多系统命令(例如 shutdown)的贮存位置。目录 /usr/sbin 中也包括了许多系统命令。/root — 根用户(超级用户)的主目录。/mnt — 该目录中通常包括系统引导后被挂载的文件系统…

linux脚本传参修改配置文件,shell脚本修改配置文件指定行的值

配置文件内容为Version1ExpireTime300MaxProcessTime15MaxQueueSize2000MaxStatisticsTime1000000StatisticsCount10根据关键字MaxStatisticsTime获取行号,修改对应的value值change_file.sh#!/bin/bashfile_name"config.xml"key_value"MaxStatisticsTime"c…

刚转Java?那准备转回.NET5吧!

再过几天就2021年了,回首今年最大的变化就是.NET5的发布,终结了.NET Framework和.NET Core两个分支。虽然因为新冠疫情原因,原定于.NET5的部分功能被推迟到.NET6了,但.NET5是一个非常非常重要的版本,会载入史册的一个版…

azure linux 多磁盘 lvm,EVE-NG扩展磁盘空间(扩展LVM卷)

环境准备系统环境:EVE-PRO-VM-2.0.4-20前期是使用ova导入安装,精简置备,40G虚拟磁盘容量。空间不足,尝试了很久,记录操作记录如下:血泪教训:操作不当有可能引起数据丢失,需要提前备份…

在 xunit 测试项目中使用依赖注入

在 xunit 测试项目中使用依赖注入Intro之前写过几篇 xunit 依赖注入的文章,今天这篇文章将结合我在 .NET Conf 上的分享,更加系统的分享一下在测试中的应用案例。之所以想分享这个话题是因为我觉得在我们开发过程中测试是非常重要的一部分,高…

linux 端口qos,linux的qos机制 - cgroup篇 (2)

这篇重点讲述cgroup如何控制blkio子系统的qos,首先看下设置blkio.weight blkio.weight_device我的理解是blkio.weight是整个io子系统的权重值,而blkio.weight_device是针对特定的major:minor 设备的权重blkio.throttle.read_bps_device blkio.throttle.w…

利用 C# 中的 FileSystemWatcher 制作一个文件夹监控小工具

利用 C# 中的 FileSystemWatcher 制作一个文件夹监控小工具独立观察员 2020 年 12 月 26 日前一段看到微信公众号 “码农读书” 上发了一篇文章《如何使用 C# 中的 FileSystemWatcher》(翻译自:https://www.infoworld.com/article/3185447/how-to-work-w…

u盘安全删除 linux,为什么要安全删除U盘

原标题:为什么要安全删除U盘移除闪存设备时会对电脑造成危害吗?我们为什么要安全的移除它们?历史上,操作系统将磁盘作为信任对象不需要突然改变状态。当读写文件时,操作系统不希望文件在读写的过程中突然消失。如果文件…