Redis---zset类型

ZSET

有序集合,这里的有序指的是升序/降序,相当于顺序是固定的

zset中的member还是要求是唯一的

ZADD

向集合中添加新的元素

操作格式:

zadd key NX \| XX GT \| LT CH INCRscore member score member...

score:因为是要保证有序,score就是进行排序的条件

member:添加的成员

NX:与前面的含义一样,只有member不存在的时候才可以添加

XX:只有member存在的时候才可以添加

GT:添加新的元素是,判定元素score要大于当前最大的score才可以更新

LT:添加新的元素是,判定元素score要小于当前最小的score才可以更新

CH:正常来讲ZADD返回值应该是新增个数,添加完CH选项,返回值除新增个数加上被修改的个数

INCR:此时命令类似ZINCRBY的效果,将元素增加上指定的score,此时只能指定一个元素和score

返回值:

新增成功的元素个数,如果没进行添加新元素,而是只进行修改的话,返回值为0

时间复杂度:

O(logN):N为有序集合中的元素个数,因为要保证有序性,所以需要找到添加位置,可以想象成二分查找,但并不是二分查找,内部实现是使用了跳表,二者结构并不相似,我的意思是二者都利用了有序性实现快速查找,致使其效率达到logN而不是N

如果score(判定条件)是一样的怎么进行排序?

如果score是一样的,那么排序就会按照字典序(按照member的字典序)进行排序

ZSET默认是按照升序进行排序的

举个例子:

cpp 复制代码
zadd key1 incr 4 张飞

ZRANGE

查看有序集合中的元素详情,有序集合,本身元素就是有先后顺序的,所以就有下标的概念

操作格式:

zrange key start end withscores

withscores:添加该选项可以查看score,也就是可以查看为什么这么排序,没有这个选项的话,只会给出结果,并不会显示根据什么排序得到这个结果的

举个例子:

cpp 复制代码
zrange key1 0 -1

ZCARD

获取zset中元素个数

返回值:

zset中的元素个数

时间复杂度:

O(1)

操作格式:

zcard key

ZCOUNT

返回分数在min和max之间的元素个数,默认情况下,min和max是都包含的,可以通过()进行排除

返回值:

满足条件的元素个数

时间复杂度:

O(logN)

现根据min找到对应的元素,在根据max找到对应的元素,因为在每个元素上还记录了该元素处于当前集合中的排名/下标,所以找到max和min,二者一减就可以得到结果,并不是通过遍历得到的!!!

操作格式:

zcount key min max

注意:

min和max是可以写成浮点数,因为zset本身就可以将score设置成浮点数

在浮点数中,存在两个特殊的值:

inf:无穷大

-inf:负无穷大,负无穷大不是无穷小,无穷小是无限接近于0的值,负无穷大与正无穷大的绝对值是一样的

通过这个命令也可以看出来,这里的member socre并不是键值对,而是普通的std::pair<>,因为要是键值对key,val的话只能通过key去查val,而这里是双向得到既可以通过member找到score,也能通过score找到member

举个例子:

cpp 复制代码
//查找key中不包含95而包含97的member
zcount key (95 97
//查找key中不包含95也不包含97的member
zcount key (95 (97
//不包含哪边,就在哪边加上(,可以理解成()表示开区间

ZRANGE

返回指定区间的元素,按照score升序排序

操作格式:

zrange key start stop withscores

withscores:不光显示找到的元素,还显示根据什么进行的排序,也就是score

时间复杂度:

O(log(N) + M)

现根据start找到对应的元素,在根据end找到对应的元素,这时O(log(N))的由来,M则是遍历处于该范围内的元素所产生的时间

返回值:

区间内的元素列表

ZREVRANGE

返回指定区间内的元素,score按照降序进行排序

操作格式:

zrevrange key start stop withscores

时间复杂度:

O(log(N) + M)

现根据start找到对应的元素,在根据end找到对应的元素,这时O(log(N))的由来,M则是遍历处于该范围内的元素所产生的时间

返回值:

区间内的元素列表

举个例子:

cpp 复制代码
zrevrange key 0 -1 withscores

ZRANGEBYSCORE

返回在min和max之间的元素,默认情况下,min和max都是包含的,不想包含的话可以通过"("进行排除

返回值:

区间内的元素列表

时间复杂度:

O(log(N) + M)

操作格式:

zrangebyscore key min max witgscores

注意:

与ZRANGE的区别就是,ZRANGE按照下标找元素的,而ZRANGEBYSCORE按照score找元素的

这个命令可能在6.2.0之后废弃,因为将该功能合并到ZRANGE中

ZPOPMAX

删除并返回最高的count元素

操作格式:

zpopmax key count

返回值:

socre和member列表

时间复杂度:

O(log(N) * M),log(N),是找到目标元素所花的时间,M是count个数

如果存在多个元素,socre(分数)相同,同时为最大值,zpopmax删的时候,仍然只删除其中一个元素,删除规则按照字典序删除的

BZPOPMAX

删除最大值的阻塞版本

操作格式:

bzpopmax key key... timeout

timeout:表示要阻塞多久,单位是秒,支持写成小时形式

时间复杂度:

O(log(N)),log(N)找到最大值所花的时间

返回值:

返回值分为三部分,第一,标识了从哪个集合中拿取的,第二,标识了member,第三标识了scorce

注意:

这里的有序集合,可以视为优先级队列,所以有的时候也需要一个带有阻塞功能的优先级队列

阻塞也是在有序集合为空的时候出发阻塞,阻塞到有其他客户端插入元素

如果集合中有元素了,则不会触发阻塞

ZPOPMIN

删除并返回最高的count元素

操作格式:

zpopmin key count

返回值:

socre和member列表

时间复杂度:

O(log(N) * M),log(N),是找到目标元素所花的时间,M是count个数

如果存在多个元素,socre(分数)相同,同时为最大值,zpopmax删的时候,仍然只删除其中一个元素,删除规则按照字典序删除的

BZPOPMIN

删除最大值的阻塞版本

操作格式:

bzpopmin key key... timeout

timeout:表示要阻塞多久,单位是秒,支持写成小时形式

时间复杂度:

O(log(N)),log(N)找到最小值所花的时间

返回值:

返回值分为三部分,第一,标识了从哪个集合中拿取的,第二,标识了member,第三标识了scorce

注意:

这里的有序集合,可以视为优先级队列,所以有的时候也需要一个带有阻塞功能的优先级队列

阻塞也是在有序集合为空的时候出发阻塞,阻塞到有其他客户端插入元素

如果集合中有元素了,则不会触发阻塞

ZRANK

返回指定元素的排名,按升序进行计算的

操作格式:

zrank key member

时间复杂度:

O(log(N)),log(N)找到该成员所花的时间

返回值:

该member的排名

ZREVERANK

返回指定元素的排名,按降序进行计算的

操作格式:

zreverank key member

时间复杂度:

O(log(N)),log(N)找到该成员所花的时间

返回值:

该member的排名

ZSCORE

返回指定元素的score

操作格式:

zscore key member

返回值:

分数

时间复杂度:

O(1)

为什么这里不是O(logN)?

因为该操作比较高频,此处相对于redis对于这样的查询操作做了特殊优化,付出了额外的空间代价

ZREM

删除指定元素

操作格式:

zrem key member member...

返回值:

本次操作删除的元素的个数

时间复杂度:

O(M*logN),M为具体删除个数,logN为每次定位元素所花的时间

ZREMRANGEBYRANK

按照升序,删除指定范围的元素,左闭右闭

操作格式

zremrangebyrank key start stop

start,stop:为下标,两个下标表示一段范围

返回值:

本次操作删除的元素的个数

时间复杂度:

O(M + logN),M为具体删除个数,logN为每次定位元素所花的时间,也就是定位开头和结尾,花费M的时间进行遍历范围内的值

举个例子:

cpp 复制代码
zremrangebyrank key1 0 -1

ZREMRANGEBYSCORE

按照分数指定的范围的元素进行删除,左闭右闭

操作格式:

zremrangebyscore key min max

返回值:

本次操作删除的元素的个数

时间复杂度:

O(M + logN),M为具体删除个数,logN为每次定位元素所花的时间,也就是定位开头和结尾,花费M的时间进行遍历范围内的值

ZINCRBY

为指定的元素的关联分数添加/减去指定分数值

操作格式:

zincrby key increment member

increment:增加/减少多少score(分数),该值可以是小数和负数

返回值:

增加/减少后元素的score(分数)

时间复杂度:

O( logN)

注意:

增加可以增加负值,可以当作减法去使用

不光会修改分数内容,也能同时移动元素位置,保持整个有序集合仍是升序的

举个例子:

cpp 复制代码
zincrby key1 -10.5 member

ZINTERSTORE

找到多个key的交集

操作格式

zinterstore destination numkeys key key... weights weight \[weight...] aggregate \

destination:要把交集结果存储到哪个zset有序集合中

numkeys:表示有多少个key

为什么要添加numkeys 这个参数?

因为该命令后面存在大量选项,使用该参数可以将key有后面选项进行分离,类似协议中将报头与有效载荷分离的操作,要不然无法区分哪几个是key哪些是选项

weights:权重,有序集合是带有分数的,此处指定的权重,相当于一个系数,添加该选项的话,那么结果的分数则是当前分数乘以权重,为该集合的该member成员的分数,再根据aggregate所选择处理集合和集合之间source方式,来得到最终结果

注意:

权重的数值可以是小数,相当于百分比

[aggregate <sum | min | max>:经过权重计算完后,那只得到了集合的成员所对应的分数,但是此处求得是交集,前置知识,相同member就是满足交集的要求,分数可以不同,所以作为交集该最新结果的分数因该根据该选项进行计算,sum是让多个相同member的socre结果进行相加,该方法也是默认方法,min是多个socre选最小的,max是多个socre选最大的

时间复杂度:

O(N * K) + O(M * log(M))

N:输入若干个有序集合,里面元素最小的个数

K:集合的个数

M:最终结果的有序集合元素个数

ZUNIONSTORE

求多个有序集合之间的并集

操作格式:

zunionstore destination numkeys key key... weights weight \[weight...] aggregate \

用法与zuinion几乎一致

时间复杂度:

O(N) + O(M * logM)

N:表示总的元素个数

M:表示总的结果集的个数

举个例子:

ZSET编码方式

ziplist:压缩列表

skiplist:跳表,简单来说就是一个复杂的"链表"

跳表的时间复杂度:O(logN)

ZSET应用场景

可以做各种排行榜,核心就是使用有序的特性

相关推荐
老大白菜19 小时前
Omnigent(omni)使用说明
服务器·数据库·microsoft
数智化管理手记19 小时前
全面预算管理执行偏差大?全面预算管理全流程落地步骤是什么
大数据·网络·数据库·人工智能·数据挖掘
倔强的石头_20 小时前
SQL 语法全兼容,但结果就是不一样——国产化迁移里最难缠的九类隐患
数据库
kobe_OKOK_20 小时前
django外键字段会自动在数据库字段后面加上_id
数据库·django·sqlite
<小智>1 天前
及时做APP开发实战(十二)-LazyForEach懒加载优化实践
数据库·鸿蒙
龙仔7251 天前
人大金仓KingbaseES V8 手动单库备份&恢复操作笔记
数据库·笔记·oracle·人大金仓
宠友信息1 天前
消息序号如何保证即时通讯源码聊天记录稳定加载
java·spring boot·redis·python·mysql·uni-app
夏贰四1 天前
数据库迁移怎样降低人力投入?数据库迁移怎么实现全量增量同步?
数据库·数据库迁移
汇智信科1 天前
图谱、向量、关键词、SQL多路一体,FastKG垂域召回率100%拉满
网络·数据库·ai编程·汇智信科·hsim·fastclaw·汇智龙虾