redis(8):数据结构-zset有序集合类型

之前已经介绍过了如何使用列表类型键存储文章 ID 列表,不过还想加 上按照文章访问量排序的功能,因为我觉得很多访客更希望看那些热门的文章。


一、介绍

在这里插入图片描述
SortedSet(zset)是Redis提供的一个非常特别的数据结构,一方面它等价于Java的数据结构Map<String, Double>,可以给每一个元素value赋予一个权重score,另一方面它又类似于TreeSet,内部的元素会按照权重score进行排序,可以得到每个元素的名次,还可以通过score的范围来获取元素的列表。
zset底层实现使用了两个数据结构,第一个是hash,第二个是跳跃列表

  1. hash的作用就是关联元素value和权重score,保障元素value的唯一性,可以通过元素value找到相应的score值。
  2. 跳跃列表的目的在于给元素value排序,根据score的范围获取元素列表。

zset和set区别

  1. 列表类型是通过链表实现的,获取靠近两端的数据速度极快,而当元素增多后, 访问中间数据的速度会较慢,所以它更加适合实现如“新鲜事”或“日志”这样很少访问中间元 素的应用。
  2. 有序集合类型是使用散列表和跳跃表(Skip list)实现的,所以即使读取位于中间 部分的数据速度也很快(时间复杂度是O(log(N)))。
  3. 列表中不能简单地调整某个元素的位置,但是有序集合可以(通过更改这个元素 的分数)。
  4. 有序集合要比列表类型更耗费内存。

有序集合类型算得上是Redis的5种数据类型中最高级的类型了,在学习时可以与列表类 型和集合类型对照理解。


二、命令

1.1.增加元素

ZADD key score member [score member …]
ZADD 命令用来向有序集合中加入一个元素和该元素的分数,如果该元素已经存在则会用新的分数替换原有的分数。ZADD命令的返回值是新加入到集合中的元素个数(不包含之 前已经存在的元素)。
假设我们用有序集合模拟计分板,现在要记录Tom、Peter和David三名运动员的分数 (分别是89分、67分和100分):

redis> ZADD scoreboard 89 Tom 67 Peter 100 David
(integer) 3 

这时我们发现Peter的分数录入有误,实际的分数应该是76分,可以用ZADD命令修改 Peter的分数:

redis> ZADD scoreboard 76 Peter 
(integer) 0 

分数不仅可以是整数,还支持双精度浮点数:

2.获得元素的分数

ZSCORE key member
示例如下:
redis> ZSCORE scoreboard Tom
“89”

3.获得排名在某个范围的元素列表

ZRANGE key start stop [WITHSCORES] 
ZREVRANGE key start stop [WITHSCORES] 

ZRANGE命令会按照元素分数从小到大的顺序返回索引从 start到stop之间的所有元素 (包含两端的元素)。ZRANGE命令与LRANGE命令十分相似,如索引都是从0开始,负数 代表从后向前查找(−1表示最后一个元素)

4.获得指定分数范围的元素

ZRANGEBYSCORE key min max [WITHSCORES]
[LIMIT offset count] ZRANGEBYSCORE 命令参数虽然多,但是都很好理解。该命令按照元素分数从小到大 的顺序返回分数在min和max之间(包含min和max)的元素

redis> ZRANGEBYSCORE scoreboard 80 100 
1) "Tom" 
2) "David" 

如果希望分数范围不包含端点值,可以在分数前加上“(”符号。例如,希望返回”80分到 100分的数据,可以含80分,但不包含100分,则稍微修改一下上面的命令即可:

redis> ZRANGEBYSCORE scoreboard 80 (100 
1) "Tom"

5.增加某个元素的分数

ZINCRBY key increment member 

ZINCRBY 命令可以增加(减少)一个元素的分数,返回值是更改后的分数。例如,想给 Jerry加 4分:

redis> ZINCRBY scoreboard 4 Jerry 
"60"

三、实践

1.实现按点击量排序

>ZINCRBY posts:page.view 1 文章ID //更新访问量,访问一次加一
>ZREVRANGE posts:page.view  $start,$end //获取访问量在start到end之间的文章ID列表

2.改进按时间排序

>ZADD posts:page.view 时间戳 文章id //添加或更新 文档id的时间戳
>ZREVRANGEBYSCORE posts:page.view  $start,$end //轻松获得指定时间范围的文章列表

四、命令拾遗

1.获得集合中元素的数量

ZCARD key 

例如:

redis> ZCARD scoreboard (integer) 6 

2.获得指定分数范围内的元素个数

ZCOUNT key min max 

例如:

redis> ZCOUNT scoreboard 90 100 
(integer) 2

ZCOUNT命令的min和max参数的特性与ZRANGEBYSCORE命令中的一样:

 redis> ZCOUNT scoreboard (89 +inf
  (integer) 2

3.删除一个或多个元素

ZREM key member [member …] 

ZREM命令的返回值是成功删除的元素数量(不包含本来就不存在的元素)。

redis> ZREM scoreboard Wendy 
(integer) 1
redis> ZCARD scoreboard 
(integer) 5 

4.按照排名范围删除元素

ZREMRANGEBYRANK key start stop 

ZREMRANGEBYRANK 命令按照元素分数从小到大的顺序(即索引 0表示最小的值) 删除处在指定排名范围内的所有元素,并返回删除的元素数量。如:

redis> ZADD testRem 1 a 2 b 3 c 4 d 5 e 6 f 
(integer) 6 
redis> ZREMRANGEBYRANK testRem 0 2 
(integer) 3 
redis> ZRANGE testRem 0 -1 
1) "d" 
2) "e" 
3) "f" 

5.按照分数范围删除元素

ZREMRANGEBYSCORE key min max 

ZREMRANGEBYSCORE命令会删除指定分数范围内的所有元素,参数min和max的特性 和ZRANGEBYSCORE命令中的一样。返回值是删除的元素数量。如:

redis> ZREMRANGEBYSCORE testRem (4 5 
(integer) 1 
redis> ZRANGE testRem 0 -1 
1) "d" 
2) "f" 

6.获得元素的排名

ZRANK key member 
ZREVRANK key member 

ZRANK命令会按照元素分数从小到大的顺序获得指定的元素的排名(从0开始,即分数 最小的元素排名为0)。如:

redis> ZRANK scoreboard Peter 
(integer) 0 

ZREVRANK命令则相反(分数最大的元素排名为0):

redis> ZREVRANK scoreboard Peter 
(integer) 4

7.计算有序集合的交集

ZINTERSTORE destination numkeys key [key …] [WEIGHTS weight [weight …]] [AGGREGATE 
SUM|MIN|MAX] 

ZINTERSTORE命令用来计算多个有序集合的交集并将结果存储在destination键中(同样 以有序集合类型存储),返回值为destination键中的元素个数。 destination键中元素的分数是由AGGREGATE参数决定的。

相关推荐
©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页