对 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,一经查实,立即删除!

相关文章

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

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

.NET Core AWS S3云存储

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

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

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

龙芯.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 — 该目录中通常包括系统引导后被挂载的文件系统…

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

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

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

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

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

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

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

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

如何在 C# 中使用 投影(Projection)

投影(Projection) 是一种可以将查询结果进行 塑性 的一种操作,你可以使用 投影 将一个 object 转成仅包含你需要属性的新对象,这篇文章中,我们就一起看看如何使用 投影 功能。C# 中的投影 LINQ 集成查询中有两个支持投影的扩展方法&#xff0…

Linux语言写的高通滤波,高通滤波器c语言实现

描述高通滤波器,又称低截止滤波器、低阻滤波器,允许高于某一截频的频率通过,而大大衰减较低频率的一种滤波器。它去掉了信号中不必要的低频成分或者说去掉了低频干扰。高通滤波器是一种让某一频率以上的信号分量通过,而对该频率以…

在 WSL Ubuntu 上使用 .NET 进行跨平台开发新手入门

翻译自 haydenb 2020年6月3日的文章《Getting started with cross-platform development using .NET on Ubuntu on WSL》 [1].NET 是一个开源软件框架,用于在 Linux、Windows 和 macOS 上构建跨平台应用程序。WSL 上的 Ubuntu [2]允许您同时为 Ubuntu 和 Windows 构…

明源云·天际,地产⾏业的Salesforce Lightning Platform

源宝导读:2020年11月6日,明源云在CIO峰会上正式对外发布了“天际开放平台”,这是明源云凝聚其20多年行业经验打造的一款企业级PaaS平台。本文将介绍我们对企业级PaaS平台的行业思考,以及为加速泛地产生态链数字化转型而做的技术创…

c程序设计语言选修难吗,欢迎大家选修C语言程序设计这门课,本帖解释一下一些常见的问题...

置顶欢迎大家选修C语言程序设计这门课,本帖解释一下一些常见的问题叶卡林娜发表于2017年01月05日首先欢迎大家选修浙大翁恺老师的C语言程序设计课程。开课2天就看到讨论区已经有这么多帖子,说明同学们的学习热情很高。结合前几次开课的经验以及目前在讨论…

IdentityServer4系列 | 支持数据持久化

一、前言在前面的篇章介绍中,一些基础配置如API资源、客户端资源等数据以及使用过程中发放的令牌等操作数据,我们都是通过将操作数据和配置数据存储在内存中进行实现的,而在实际开发生产中,我们需要考虑如何处理数据持久化呢&…

c语言修仙受控可看吗,强推三本神奇到爆的小说,c语言修仙,程序员与修真会擦出什么火花...

大家好,我是小龙。今天我给大家推荐三本神奇到爆的小说,c语言修仙,程序员与修真会擦出什么火花!一《c语言修仙》【一十四洲】【简介】: 林浔是一个程序员,通宵编代码后发现自己身体内多了一个程序输入窗口。他尝试编了一个循环程序…

【Vue】Vue与ASP.NET Core WebAPI的集成

SPA单页面应用已经遍地开花,熟知的三大框架,Angular、Vue和React,其中Angular与React均可集成至ASP.NET Core,且提供了相关了中间件。但是Vue没有:“As far as I’m aware, we don’t have plans to introduce Vue-specific featu…

引入Jaeger——封装

随着微服务的普及,微服务间的调用全链路跟踪也火了起来,Jaeger(https://www.jaegertracing.io/)是CNCF孵化的全链路跟踪型项目,在.net core中,提供了一个Jaeger的Nuget(https://github.com/jaegertracing/jaeger-client-csharp)包…

临近年关,发生两起磁盘占满引发的服务下线故障

一口气说两个因为磁盘空间不足引发的应用故障。作为拿起键盘一把梭的Coder, 开发--->部署-->收工--->心旷神怡,滋一口82年的可乐.过了几个月,服务突然下线了!CTO又有杀程序员祭天的理由了!事故1:Azure App Se…