Redis —— 基本数据类型 Set Zset (三)

4. Set

一个集合中最多放 2^31-1 个元素,元素之间无序且不允许重复。

除针对集合内部元素的 增删查改等命令,redis中还有集合间的并,交,差运算。

4.1 集合元素内操作

4.1.1 SADD

bash 复制代码
SADD key member [member ...]

将 一/多元素放入 set 中,重复的无法放入。

返:成功添加的元素个数

时间复杂度:O(1)

bash 复制代码
127.0.0.1:6379> SADD myset 1 2 3 4 5 6 7 8 9
9
127.0.0.1:6379> SMEMBERS myset
1
2
3
4
5
6
7
8
9

4.1.2 SMEMBERS

bash 复制代码
SMEMBERS key

获取 set 中全部元素,元素间是无序的

返:所有元素列表

时间复杂度:O(1)

bash 复制代码
127.0.0.1:6379> SADD myset 1 2 3 4 5 6 7 8 9
9
127.0.0.1:6379> SMEMBERS myset
1
2
3
4
5
6
7
8
9

4.1.3 SISMEMBER

bash 复制代码
SISMEMBER key member

判断某一元素是否在 set 中

返:1:在;0:不在或key不存在

时间复杂度:O(1)

bash 复制代码
127.0.0.1:6379> SMEMBERS myset
1
4
 !!!
hello
6
9
8
2
5
7
3
world
127.0.0.1:6379> SISMEMBER myset "hello"
1
127.0.0.1:6379> SISMEMBER myset "helo"
0

4.1.4 SCARD

bash 复制代码
SCARD key

获取 set 的基数(cardinality),即 set 中的元素个数

返:set 中的元素个数

时间复杂度:O(1)

bash 复制代码
127.0.0.1:6379> SMEMBERS myset
1
4
 !!!
hello
6
9
8
2
5
7
3
world
127.0.0.1:6379> SCARD myset
12

4.1.5 SPOP

bash 复制代码
SPOP key [count]

从 set 中删除 一/多 个元素,由于 set 中的元素是无序的,取的元素是随机 的。

返:取出的元素

时间复杂度:O(n), n 是 元素个数

bash 复制代码
127.0.0.1:6379> SPOP myset
5
127.0.0.1:6379> spop myset 3
7
3
world

4.1.6 SMOVE

bash 复制代码
SMOVE source destination membe

将指定的某一元素从 setA 取出放入 setB 中

返: 1:成功;0:失败

时间复杂度:O(1)

bash 复制代码
127.0.0.1:6379> smove myset myset1 "hello"
1
127.0.0.1:6379> SMEMBERS myset1
hello

4.1.7 SREM

bash 复制代码
SREM key member [member ...]

将指定元素从 set 中删除

返:删除的元素个数

时间复杂度:O(n), n 是 元素个数

bash 复制代码
127.0.0.1:6379> SREM myset 1 2 3
2
127.0.0.1:6379> SMEMBERS myset
4
 !!!
6
9
8

4.2 集合间元素操作

4.2.1 SINTER

bash 复制代码
SINTER key [key ...]

获取给定 set 的交集元素

返:交集元素

时间复杂度:O(n*m), n :最小集合元素个数, M 最大集合元素个数

bash 复制代码
127.0.0.1:6379> SMEMBERS myset
4
 !!!
6
9
8

127.0.0.1:6379> SMEMBERS myset2
9
 !!!
4
hello
6
8
127.0.0.1:6379> SINTER myset myset2
4
 !!!
6
9
8

4.1.2 SINTERSTORE

bash 复制代码
SINTERSTORE destination key [key ...]

将交集元素存入指定 set 中

返:交集元素个数

时间复杂度:O(n*m), n :最小集合元素个数, M 最大集合元素个数

bash 复制代码
127.0.0.1:6379> SINTERSTORE myset3 myset myset2
5
127.0.0.1:6379> SMEMBERS myset3
6
4
9
 !!!
8

4.1.3 SUNION

bash 复制代码
SUNION key [key ...]

取集合的并集元素

返:并集元素

时间复杂度:O(n),n:所有集合元素个数之和

bash 复制代码
127.0.0.1:6379> SMEMBERS myset
4
 !!!
6
9
8
127.0.0.1:6379> SMEMBERS myset1
hello
127.0.0.1:6379> sunion myset myset1
9
 !!!
4
hello
6
8

4.2.4 SUNIONSTORE

bash 复制代码
SUNIONSTORE destination key [key ...]

将并集元素存入指定 set 中

返:并集元素个数加粗样式

时间复杂度:O(n),n:所有集合元素个数之和

bash 复制代码
127.0.0.1:6379> SUNIONSTORE myset2 myset myset1
6
127.0.0.1:6379> SMEMBERS myset2
9
 !!!
4
hello
6
8

4.2.5 SDIFF

bash 复制代码
SDIFF key [key ...]

获取给定 set 的差集

返:差集元素

时间复杂度:O(n),n:所有集合元素个数之和

bash 复制代码
127.0.0.1:6379> SMEMBERS myset
4
 !!!
6
9
8
127.0.0.1:6379> SMEMBERS myset2
9
 !!!
4
hello
6
8
127.0.0.1:6379> SDIFF myset2 myset
hello

4.2.6 SDIFFSTORE

bash 复制代码
SDIFFSTORE destination key [key...]

将差集存入指定 set 中

返:差集元素个数

时间复杂度:O(n),n:所有集合元素个数之和

bash 复制代码
127.0.0.1:6379> SMEMBERS myset
4
 !!!
6
9
8
127.0.0.1:6379> SMEMBERS myset2
9
 !!!
4
hello
6
8
127.0.0.1:6379> SDIFFSTORE myset4 myset2 myset
1
127.0.0.1:6379> SMEMBERS myset4
hello

4.3 内部编码

  • intset (整数集合):集合中都是整数,且元素个数小于 set-max-intset-entrier 配置(默认 512 个)时,作 set 的内部实现,减小内存使用
  • hashtable(哈希表):不满足 intset 条件时,用 hashtable 作 set 内部实现。

4.4 使用场景

  • 给用户添加标签,eg:喜欢音乐,喜欢体育......
    伪代码:
  1. 给用户加标签:
bash 复制代码
sadd user:1:tags tag1 tag2 tag5
sadd user:2:tags tag2 tag3 tag5
...
  1. 给标签添加用户
bash 复制代码
sadd tag1:users user:1 user:3
sadd tag2:users user:1 user:2 user:3
...
  1. 删除用户标签
bash 复制代码
srem user:1:tags tag1 tag5
...
  1. 删除标签下的用户
bash 复制代码
srem tag1:users user:1
srem tag5:users user:1
...
  1. 计算用户的共同标签
bash 复制代码
sinter user:1:tags user:2:tags

5. Zset

有序集合,就是给集合中的每个元素装备了一个对应的浮点型的分数(score),有序就是依据这种分数的。

有序集中元素不能重复,但是元素的分数可以重复。

5.1 集合内元素操作

5.1.1 ZADD

bash 复制代码
ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member
...]
  • XX:仅用于更新存在的元素,不会添新元素
  • NX:仅用于添新元素,不会更新已有元素
  • CH:ZADD 默认返回添加的元素个数,加上该选项后,还会包含更新的元素个数
  • INCR:与 ZINCRBY 效果类似,将元素分数加上指定分数。此时只能指定一个元素和分数

添加或更新 指定元素及其关联分数到 zset 中,分数应为 double型, +inf/-inf 作为正负极限也是合法

时间复杂度:O(log(N))

返:添加成功的元素个数(不算更新的)

bash 复制代码
127.0.0.1:6379> ZADD zset 111 "1" 222 "2" 333 "3"
3

5.1.2 ZCARD

bash 复制代码
ZCARD key

获取一个 zset 的基数,即 zset 中的元素个数

返:zset 内元素个数

时间复杂度:O(1)

bash 复制代码
127.0.0.1:6379> ZCARD zset
3

5.1.3 ZCOUNT

bash 复制代码
ZCOUNT key min max

返回分数在 min 和 max 间的元素个数,默认包含 min 和 max,可以通过 排除。

返:满足条件的元素列表个数

时间复杂度:O(log(N))

bash 复制代码
127.0.0.1:6379> ZCOUNT zset 100 360
3

5.1.4 ZRANGE

bash 复制代码
ZRANGE key start stop [WITHSCORES]

返回指定区间的元素,分数按照升序,加上 WITHSCORE 可以带分数返回

返:区间内的元素列表

时间复杂度:O(log(N)+M)

bash 复制代码
127.0.0.1:6379> ZRANGE zset 0 -1
1
2
3
127.0.0.1:6379> ZRANGE zset 0 -1 withscores
1
111
2
222
3
333

5.1.5 ZREVRANGE

bash 复制代码
REVRANGE key start stop [WITHSCORES]

ZRANGE ,但分数按照降序,也可加WITHSCORES

返:区域内元素列表

时间复杂度:O(log(N)+M)

bash 复制代码
127.0.0.1:6379> ZREVRANGE zset 0 -1 
3
2
1
127.0.0.1:6379> ZREVRANGE zset 0 -1 withscores
3
333
2
222
1
111

5.1.6 ZRANGEBYSCORE

bash 复制代码
ZRANGEBYSCORE key min max [WITHSCORES]

返回分数在 min 和 max 间的元素,默认包含 min 和 max,可以通过 排除。

返:区域内元素列表

时间复杂度:O(log(N)+M)

bash 复制代码
127.0.0.1:6379> ZRANGEBYSCORE zset (111 333 
2
3
127.0.0.1:6379> ZRANGEBYSCORE zset (111 333 withscores
2
222
3
333

5.1.7 ZPOPMAX

bash 复制代码
ZPOPMAX key [count]

删除并返回分数最高的 count 个元素。

返:分数和元素列表

时间复杂度:O(log(N) * M)

bash 复制代码
127.0.0.1:6379> ZPOPMAX zset 
3
333

5.1.8 BZPOPMAX

bash 复制代码
BZPOPMAX key [key ...] timeout

ZPOPMAX 阻塞版

返:元素列表

时间复杂度:O(log(N))

bash 复制代码
127.0.0.1:6379> BZPOPMAX zset 10
zset
2
222

5.1.9 ZPOPMIN

bash 复制代码
ZPOPMIN key [count]

删除并返回分数最低的 count 个元素。

返:分数和元素列表

时间复杂度:O(log(N) * M)

和 ZPOPMAX 类似不再展示

5.1.10 BZPOPMIN

bash 复制代码
BZPOPMIN key [key ...] timeout

ZPOPMIN 阻塞版

返:元素列表

时间复杂度:O(log(N))

和 BZPOPMAX 类似不再展示

5.1.11 ZRANK / ZREVRANK

bash 复制代码
ZRANK key member

返回指定元素的排名,按升/降序

返:排名

时间复杂度:O(log(N))

bash 复制代码
127.0.0.1:6379> ZRANGE zset 0 -1 
1
3
4
5
6
127.0.0.1:6379> ZRANK zset 3
1

5.1.12 ZSCORE

bash 复制代码
 ZSCORE key member

返:指定元素的分数

时间复杂度:O(1)

bash 复制代码
127.0.0.1:6379> ZADD zset 333 "3" 444 "4" 555 "5" 666 "6"
4
127.0.0.1:6379> ZSCORE zset 6
666

5.1.13 ZREM

bash 复制代码
ZREM key member [member ...]

删除指定 一/多 个元素

返:删除的元素个数

时间复杂度:O(M*log(N))

bash 复制代码
127.0.0.1:6379> ZRANGE zset 0 -1 
1
3
4
5
6
127.0.0.1:6379> ZREM zset 4
1
127.0.0.1:6379> ZRANGE zset 0 -1 
1
3
5
6

5.1.14 ZREMRANGEBYRANK

bash 复制代码
ZREMRANGEBYRANK key start stop

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

返:删除的元素个数

时间复杂度:O(log(N)+M)

bash 复制代码
127.0.0.1:6379> ZRANGE zset 0 -1 
1
3
5
6
127.0.0.1:6379> ZREMRANGEBYRANK zset 2 3
2
127.0.0.1:6379> ZRANGE zset 0 -1 
1
3

5.1.15 ZREMRANGEBYSCORE

bash 复制代码
ZREMRANGEBYSCORE key min max

按分数删除指定范围元素,左闭右闭

返:删除的元素个数

时间复杂度:O(log(N)+M)

bash 复制代码
127.0.0.1:6379> ZADD zset 222 "2" 444 "4" 555 "5" 666 "6"
4
127.0.0.1:6379> ZRANGE zset 0 -1 
1
2
3
4
5
6
127.0.0.1:6379> ZREMRANGEBYSCORE zset 400 666
3
127.0.0.1:6379> ZRANGE zset 0 -1 
1
2
3

5.1.16 ZINCRBY

bash 复制代码
ZINCRBY key increment member

给指定元素的分数加指定分数

返:加后元素的分数

时间复杂度:O(log(N))

bash 复制代码
127.0.0.1:6379> ZINCRBY zset 1 1
112

5. 2 集合间元素操作

5.2.1 ZINTERSTORE

bash 复制代码
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight
[weight ...]] [AGGREGATE <SUM | MIN | MAX>]

取出有序集中元素的交集并存入目标有序集中,合并时以元素为单位进行,元素分数按聚合方式和权重获取新值。

返:目标集中元素个数

时间复杂度:O(NK)+O(Mlog(M))

N :有序集合中最小的有序集合的元素个数;

K :几个有序集合;

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

bash 复制代码
127.0.0.1:6379> ZRANGE zset1 0 -1
1
7
8
9
127.0.0.1:6379> ZRANGE zset 0 -1
1
2
3
127.0.0.1:6379> ZINTERSTORE zset2 2 zset zset1
1
127.0.0.1:6379> ZRANGE zset2 0 -1 
1

5.2.2 ZUNIONSTORE

bash 复制代码
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight
[weight ...]] [AGGREGATE <SUM | MIN | MAX>]

取出有序集中元素的并集并存入指定有序集中,合并时以元素为单位进行,元素分数按聚合方式和权重获取新值。

返:目标集中元素个数

时间复杂度:O(N)+O(M*log(M))

N :集合总元素个数;

M :结果集合的元素个数。

bash 复制代码
127.0.0.1:6379> ZRANGE zset1 0 -1
1
7
8
9
127.0.0.1:6379> ZRANGE zset 0 -1
1
2
3
127.0.0.1:6379> ZUNIONSTORE zset3 2 zset zset1
6
127.0.0.1:6379> ZRANGE zset3 0 -1 
1
2
3
7
8
9

5.3 内部编码

  • ziplist (压缩链表):集合元素个数小于 zset-max-ziplist-entries 配置(默认 128 个),且元素值均小于 zset-max-ziplist-value 配置(默认 64 字节)时,作 zset 的内部实现,ziplist 可以减小内存消耗
  • skiplist(跳表):不满足 ziplist 的条件,则用其作 zset 的内部实现,因为此时 ziplist 的操作效率会下降。

5.4 使用场景

典型场景------排行榜系统

伪代码:

  1. 添加赞数
bash 复制代码
zadd user:ranking:2022-03-15 3 james

之后再有点赞,则用 zincrby

  1. 取消用户赞数
bash 复制代码
zrem user:ranking:2022-03-15 tom
  1. 展示获赞数前十用户
bash 复制代码
zrevrangebyrank user:ranking:2022-03-15 0 9
  1. 展示用户信息以及分数
bash 复制代码
hgetall user:info:tom
zscore user:ranking:2022-03-15 mike
zrank user:ranking:2022-03-15 mike
相关推荐
记录者t4 小时前
redis常见问题:大key
数据库·redis
青石路4 小时前
如果写Redis序列化与读Redis序列化不一致,你觉得会发生什么
java·redis
難釋懷5 小时前
Nginx代理https请求
redis·nginx·https
流星白龙14 小时前
【Redis】2.Redis重大版本
数据库·redis·junit
流星白龙14 小时前
【Redis】7.Hash表
数据库·redis·哈希算法
流星白龙15 小时前
【Redis】4.基本全局命令
数据库·redis·缓存
流星白龙18 小时前
【Redis】3.Redis安装与命令行客户端
数据库·redis·缓存
Season4501 天前
Redis命令 (generic即通用命令)
数据库·redis·bootstrap
我不想名字重复1 天前
redis缓存和数据库数据保持一致
数据库·redis·缓存
流星白龙1 天前
【Redis】6.计数其他命令
数据库·redis·缓存