Redis-zset有序集合
目录
1.介绍:
2.普通命令:
zadd:
zrange:
zreverange:
zrangebyscore:
zcard:
zcount:
zpopmax:
bzpopmax:
zpopmin:
bzpopmin:
zrank:
zrevrank:
zscore:
zrem:
zremrangebyramk:
zremrangebyscore:
zincrby:
2.集合间的操作:
交集:zinterstore:
并集:zunionstore:
3.内部编码:
4.使用场景:
1.介绍:
Zset:有序集合:保留了集合的提点,不能有重复成员;并且还增加了一些特点:每个元素member都有一个唯一的浮点类型的分数(score)与之相关联,这使得有序集合中的元素可以维护有序性,这里的有序排序就是以分数为依据进行排序的(默认为升序)。
有序集合中的元素不可以重复,但分数可以重复,按照分数进行排序时,若分数相同,则按照元素的字典序排序。
注意:member 和score以类似于java中的pair的关系存在,并不是键值对的关系。对于有序集合,既可以通过member找到score,也可以通过score找到member.
2.普通命令:
zadd:
作用:添加或更新指定的元素到zset中,分数要符合double类型,+inf和-inf作为正负极限分数是允许的。
语法:zadd key [NX|XX] [GT|LT] [CH|INCR] score member [score member....]
时间复杂度:O(logN),对于每一个添加任务,N是有序集合中元素的个数。
返回值:本次添加成功的元素个数
添加元素时,既要添加元素,也要添加分数。
其中的可选项:
[NX|XX]:NX:用于添加新元素,当元素已经存在时,更新失败;
XX: 用于更新已经存在的元素,当元素不存在时,添加失败。
当不添加这个选项的时候,若添加的元素在集合中已经存在,则更新score; 若不存在,则添加新元素。
[GT|LT] :
GT:greater then:更新元素分数的时候,更新的分数比原分数大,则更新成功,否则更新失败;
LT: less then: 更新元素分数的时候,更新的分数比原分数小,则更新成功,否则更新失败;
[CH | INCR]:
CH:zadd的返回值默认是新增元素的个数,添加这个选项后,返回值中也包含更新元素的个数。
INCR:指定特定的元素为其score加上特定的分数,只能指定一个元素和分数。
zrange:
作用:查看指定下标区间集合中元素详情,按照分数升序排序。
语法:zrange key start stop [withscore]
时间复杂度:O(logN+M),N是有序集合中元素的个数,M为结果区间的长度。
返回值:区间内元素列表
[start,stop]构成下标区间,闭区间。从0开始,支持负数。
withscore选项:带上这个选项后,会将分数也显示出来。
zset虽然是集合,但是是有序的,因此可以通过下标查找元素。
zreverange:
作用:查看指定下标区间集合中元素详情,按照分数降序排序。
语法:zrange key start stop [withscore]
时间复杂度:O(logN+M),N是有序集合中元素的个数,M为结果区间的长度。
返回值:区间内元素列表
说明和zrange命令相同。
zrangebyscore:
作用:查看分数在min和max之间的元素集合。min和max都是包含的,可以通过(排除。
语法:zrangebyscore key min max [withscore]
时间复杂度:O(logN+M),N是有序集合中元素的个数,M为结果区间的长度。
返回值:区间内元素列表
zcard:
作用:获取集合中元素的个数。
语法:zcard key
时间复杂度:O(1)
返回值:集合内元素的个数。
zcount:
作用:返回min到max分数区间的元素个数,min和max都是包含的,可以通过( 排除。
语法:zcount key min max
时间复杂度:O(logN),N是有序集合中元素的个数。
返回值:满足条件列表的元素个数
若不想包含左区间或右区间,可以用( 进行排除:
排除左区间: zcount key (min max
排除右区间: zcount key min (max
min和max可以是浮点数。
zpopmax:
作用:删除并返回score最高的count个元素。
语法:zpopmax key [count]
时间复杂度:O(logN+M),N:有序集合中元素的个数,M要删除元素的个数:count
返回值:被删除的元素列表
当存在多个元素的分数相同时,只会删除一个,按照member的字典序删除。
zset时有序的,删除最大元素,实际上就是删除末尾元素,其实可以记录最后一个元素,每次删除的时候,只需要删除标记的元素即可,不需要遍历整个集合,时间复杂度就是O(1),可以提高时间复杂度;
但redis并没有这样操作,而是直接调用一个通用的 “删除函数”:给定一个member值,进行查找,找到指定位置进行删除。虽然上面的方案可以优化,但优化的力度非常小,后续是否会优化这里尚未可知。
bzpopmax:
zpopmax的阻塞版本。
作用:删除并返回score最高的元素,若集合为空,则进入阻塞状态。
语法:bzpopmax key [key...] timeout
时间复杂度:O(logN),N:删除最大值花费的时间
返回值:被删除的元素列表
timeout:最长阻塞时间,单位为秒,可以是小数,
这个命令就类似于带有阻塞功能的 优先级队列。
这个命令可以同时读取多个集合。
zpopmin:
作用:删除并返回score最小的count个元素。
语法:zpopmin key [count]
时间复杂度:O(logN+M),N:有序集合中元素的个数,M要删除元素的个数:count
返回值:被删除的元素列表
这个和zpopmax的逻辑是一样的。
bzpopmin:
zpopmin的阻塞版本。
作用:删除并返回score最小的元素,若集合为空,则进入阻塞状态。
语法:bzpopmin key [key...] timeout
时间复杂度:O(logN),N:删除最小值花费的时间
返回值:被删除的元素列表
这个和bzpopmax的逻辑是一样的。
zrank:
作用:返回只当元素的下标(排名)(按照升序排列)。
语法:zrank key member
时间复杂度:O(logN),N:集合中元素的个数
返回值:排名
zrevrank:
作用:返回只当元素的下标(排名)(按照降序排列)。
语法:zrank key member
时间复杂度:O(logN),N:集合中元素的个数
返回值:排名
zscore:
作用:返回指定元素的分数。
语法:zscore key member
时间复杂度:O(1)
返回值:分数
这里的时间复杂度为O(1):由于这样的查询操作使用的可能比较频繁,因此redis对这样的查询操作进行了优化,付出了空间代价,根据meber查找元素的时间复杂度为哦(logN),这里优化到
O(1)。
zrem:
作用:删除指定元素
语法:zrem key member [member...]
时间复杂度:O(M*logN):M为要删除的元素的个数,N:集合中元素总个数
返回值:删除元素的个数
zremrangebyramk:
作用:按照升序,删除指定下标区间的元素,start和stop都是包含的,可以通过( 排除。
语法:zremrangebyrank key start stop
时间复杂度:O(M+logN):M:删除的区间大小,N:集合中元素总个数
返回值:删除元素的个数
[start,stop]为删除区间,闭区间,
zremrangebyscore:
作用:按照升序,删除指定分数区间的元素,min和max都是包含的,可以通过( 排除。
语法:zremrangebyscore key min max
时间复杂度:O(M+logN):M:删除的区间大小,N:集合中元素总个数
返回值:删除元素的个数
[min,max]为分数区间的范围,闭区间,可以为浮点数。
zincrby:
作用:为指定的元素分数添加指定的分数。
语法:zincrby key incrnumber member
时间复杂度:O(logN)N:集合中元素总个数
返回值:增加后元素的分数。
2.集合间的操作:
有序集合间的操作有求交集,并集。
交集:zinterstore:
作用:求出给定集合中元素的交集,并保存到目标有序集合key中;合并的过程中,以元素为单位进行合并;元素对应的分数按照不同的集合方式和权重得到新的分数。
语法: zinterstore key numbers key [key,...] [weights weight [weight,....]] [aggregate <sum | min | max>]
时间复杂度:O(M*logN+N*K) N:输入的有序集合中,最小的集合个数;M:最终结果的有序集合个数,k: 输入的有序集合的个数:numbers
返回值:目标集合中指定元素的个数
numbers:求交集的集合个数,
wights:对不同集合的分数指定特定的权重,
aggregate: 返回的分数按照指定规则返回,
并集:zunionstore:
作用:求出给定集合中元素的并集,并保存到目标有序集合key中;合并的过程中,以元素为单位进行合并;元素对应的分数按照不同的集合方式和权重得到新的分数。
语法: zunionstore key numbers key [key,...] [weights weight [weight,....]] [aggregate <sum | min | max>]
时间复杂度:O(M*logN+N*K) N:输入的有序集合中,最小的集合个数;M:最终结果的有序集合个数,k: 输入的有序集合的个数:numbers
返回值:目标集合中指定元素的个数
numbers:求并集的集合个数,
wights:对不同集合的分数指定特定的权重,
aggregate: 返回的分数按照指定规则返回,
3.内部编码:
有序集合的内部编码有两种:ziplist(压缩列表),skiplist(跳表)
1.当集合中的元素个数小于zset-max-ziplist-entries 配置(默认 128 个),同时,每个元素的值都小于zset-max-ziplist-value 配置(默认 64 字节)时,Redis 会⽤ ziplist 来作为有序集合的内部实现,ziplist 可以有效减少内存的使⽤。
2.当 ziplist 条件不满⾜时,有序集合会使⽤ skiplist 作为内部实现,因为此时ziplist 的操作效率会下降。
跳表就是一个复杂链表,按照返回获取元素,类似于B+数。
4.使用场景:
排行榜。各种涉及到排行榜的都可以通过有序集合来实现。
类似于:微博热搜,游戏天体排行,成绩排行....
对于游戏分数排行,将用户的id和游戏分数以有序集合的形式存储到集合中,就自然的形成了一个排序的集合,并且可以根据分数的变动,随时更新排序集合。