版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zx711166/article/details/82837346
有序集合的内部编码
有序集合类型的内部编码有两种
- ziplist(压缩列表):当有序集合的元素个数小于zset-max-ziplist-entries配置(默认128个),同时每个元素的值小于zset-max-ziplist-value配置(默认64个字节)时,Redis会用ziplist来作为有序集合的内部实现,ziplist可以有效减少内存使用。
- skiplist(跳跃表):当ziplist条件不满足时,有序集合会使用skiplist作为内部实现,因为此时zip的读写效率会下降。
下面用示例来说明:
当元素个数较少且每个元素较小时,内部编码为ziplist:
127.0.0.1:6379> zadd zsetkey 50 a 60 b 30 c
(integer) 3
127.0.0.1:6379> object encoding zsetkey
"ziplist"
当元素个数超过128个,内部编码变为skiplist:
...待输入...
当某个元素大于64个字节时,内部编码也会变为skiplist:
127.0.0.1:6379> zadd zsetkey 50 a 60 b 30 '闪烁的太阳已越过高傲的山峦,幽谷中的光点有若泡沫浮起。'
(integer) 1
127.0.0.1:6379> object encoding zsetkey
"skiplist"
有序集合结构
结构依然还是key-value的结构,key还是字符串类型,value是由两个部分组成;score表示分值,value是实际的值,由分值大小组成有序的集合。
集合 VS 有序集合
集合(Set) | 有序集合(Zset) |
---|---|
无重复元素 | 无重复元素 |
无序 | 有序 |
element | element + score |
列表 VS 有序集合
集合(List) | 有序集合(Zset) |
---|---|
可以有重复元素 | 无重复元素 |
有序 | 有序 |
element | element + score |
有序集合类型的相关命令
zadd
- zadd key score element [[score element ] [score element ] …]:添加score和element。
- 若某个 element 已经是有序集的成员,那么更新这个 element 的 score 值,并通过重新插入这个 element 元素,来保证该 element 在正确的位置上。
- score 值可以是整数值或双精度浮点数。
- 时间复杂度:O(M*log(N)), N 是有序集的基数, M 为成功添加的新成员的数量。
- 如果 key 不存在,则创建一个空的有序集并执行 zadd 操作。当 key 存在但不是有序集类型时,返回一个错误。
# 添加单个元素
redis> zadd page_rank 10 google.com
(integer) 1
# 添加多个元素
redis> zadd page_rank 9 baidu.com 8 bing.com
(integer) 2
#使用 withscores 选项,来让成员和它的 score 值一并返回
redis> zrange page_rank 0 -1 withscores
1) "bing.com"
2) "8"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
# 添加已存在元素,且 score 值不变
redis> zadd page_rank 10 google.com
(integer) 0
redis> zrange page_rank 0 -1 withscores # 没有改变
1) "bing.com"
2) "8"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
# 添加已存在元素,但是改变 score 值
redis> zadd page_rank 6 bing.com
(integer) 0
# bing.com 元素的 score 值被改变
redis> zrange page_rank 0 -1 withscores 1) "bing.com"
2) "6"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
zrem
- zrem key element [element…]:移除有序集 key 中的一个或多个成员,不存在的成员将被忽略。
- 当 key 存在但不是有序集类型时,返回一个错误。
- 时间复杂度:O(M*log(N)), N 为有序集的基数, M 为被成功移除的成员的数量。
# 测试数据
redis> zrange page_rank 0 -1 withscores
1) "bing.com"
2) "8"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
# 移除单个元素
redis> zrem page_rank google.com
(integer) 1
redis> zrange page_rank 0 -1 withscores
1) "bing.com"
2) "8"
3) "baidu.com"
4) "9"
# 移除多个元素
redis> zrem page_rank baidu.com bing.com
(integer) 2
redis> zrange page_rank 0 -1 withscores
(empty list or set)
# 移除不存在元素
redis> zrem page_rank non-exists-element
(integer) 0
zscore
- zscore key element:返回有序集 key 中,成员 element 的 score 值。
- 如果 element 元素不是有序集 key 的成员,或 key 不存在,返回 nil 。
- 时间复杂度:O(1) 。
# 测试数据
redis> zrange salary 0 -1 withscores
1) "tom"
2) "2000"
3) "peter"
4) "3500"
5) "jack"
6) "5000"
# 注意返回值是字符串
redis> zscore salary peter
"3500"
zincrby
- zincrby key increScore element:增加或减少元素的分数。
- 当 key 不存在,或 element 不是 key 的成员时, zincrby key increment element 等同于 zadd key increment member 。当 key 不是有序集类型时,返回一个错误。
- 时间复杂度:O(log(N))。
redis> zscore salary tom
"2000"
redis> zincrby salary 2000 tom
"4000"
zcard
- zcard key:返回元素的总个数。
- 时间复杂度:O(1) 。
- 当 key 存在且是有序集类型时,返回有序集的基数。当 key 不存在时,返回 0 。
# 添加一个成员
redis > zadd salary 2000 tom
(integer) 1
redis > zcard salary
(integer) 1
# 再添加一个成员
redis > zadd salary 5000 jack
(integer) 1
redis > zcard salary
(integer) 2
# 对不存在的 key 进行 ZCARD 操作
redis > exists non_exists_key
(integer) 0
redis > zcard non_exists_key
(integer) 0
zrange
- zrange key start end [withscores]:返回指定索引范围内的升序元素[分值]。
- 时间复杂度:O(log(N)+M), N 为有序集的基数,而 M 为结果集的基数。
zrangebyscore
- zrangebyscore key minScore maxScore [withscores]:返回指定分数围内的升序元素[分值]。
- 时间复杂度:O(log(N)+M), N 为有序集的基数,而 M 为结果集的基数。
zcount
- zcount key minScore maxScore:返回有序集合内再指定分数范围内的个数。
- 时间复杂度:O(log(N)), N 为有序集的基数。
zremrangebyrank
- zremrangebyrank key start end:删除指定排名内的升序元素。
- 时间复杂度:O(log(N)+M), N 为有序集的基数,而 M 为被移除成员的数量。
zremrangebyscore
- zremrangebyscore key minScore maxScore:删除指定分数内的升序元素。
- 时间复杂度:O(log(N)+M), N 为有序集的基数,而 M 为被移除成员的数量。
实战
- 排行榜:搜索排行榜、关注排行榜等