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:喜欢音乐,喜欢体育......
伪代码:
- 给用户加标签:
bash
sadd user:1:tags tag1 tag2 tag5
sadd user:2:tags tag2 tag3 tag5
...
- 给标签添加用户
bash
sadd tag1:users user:1 user:3
sadd tag2:users user:1 user:2 user:3
...
- 删除用户标签
bash
srem user:1:tags tag1 tag5
...
- 删除标签下的用户
bash
srem tag1:users user:1
srem tag5:users user: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 使用场景
典型场景------排行榜系统
伪代码:
- 添加赞数
bash
zadd user:ranking:2022-03-15 3 james
之后再有点赞,则用 zincrby
- 取消用户赞数
bash
zrem user:ranking:2022-03-15 tom
- 展示获赞数前十用户
bash
zrevrangebyrank user:ranking:2022-03-15 0 9
- 展示用户信息以及分数
bash
hgetall user:info:tom
zscore user:ranking:2022-03-15 mike
zrank user:ranking:2022-03-15 mike