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参数决定的。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
Redis中的zset有序集合,而set是无序集合。 在zset中,每个元素都有一个score字段,通过score和index来进行排序。zset的实现是使用了两种数据结构,分别是跳跃表和字典。跳跃表用于实现元素的有序排列,而字典用于实现元素的唯一性。zset的插入、删除和查找操作的时间复杂度都是O(logN)。 而set是一个无序的字符串集合,集合中的元素不可重复。在set中,元素的插入、删除和查找操作的时间复杂度都是O(1)。set的底层实现是通过哈希表来存储元素,类似于Java中的Hashtable集合。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [9. redis 数据结构-set、zset](https://blog.csdn.net/wojiuguowei/article/details/81866600)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Redis学习笔记(九)---Redis数据类Set 和 Zset](https://blog.csdn.net/TheWindOfSon/article/details/104169173)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

water___Wang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值