Redis ⑦-set | Zset
set类型基本介绍
set 为集合,该集合为无序集合,可以存储多个不同的数据类型,包括字符串、整数、浮点数等。
集合中的元素是唯一的,不可重复。
set类型常用命令
SADD
SADD key member [member...]
- 集合中的值称为
member
- 将一个或多个
member
元素加入到集合key
当中,已经存在于集合的member
元素将被忽略。 - 返回成功添加的元素的数量。
SMEMEBRS
SMEMBERS key
- 返回集合
key
中的所有成员。
SISMEMEBERS
SISMEMBER key member
- 判断
member
是否是集合key
的成员。 - 返回 1 表示
member
是集合key
的成员,返回 0 表示member
不是集合key
的成员。
SCARD
SCARD key
- 返回集合
key
的基数(元素的数量)。
SPOP
SPOP key [count]
- 由于 set 中的元素是无序的,所以删除元素是随机的。
- 随机移除并返回集合
key
中的一个元素,如果不写count
参数,则随机移除并返回一个元素。否则随机移除并返回count
个元素。
SRANDMEMBER
SRANDMEMBER key [count]
- 随机返回集合
key
中的一个元素,如果不写count
参数,则随机返回一个元素。否则随机返回count
个元素。
SMOVE
SMOVE source destination member
- 将集合
source
中的member
元素移动到集合destination
中。 - 如果
member
元素不存在于source
集合中,则不进行任何操作,返回 0。 - 如果
member
元素已经存在于destination
集合中,则不进行任何操作,返回 0。 - 如果
member
元素成功地从source
集合中移除并添加到destination
集合中,则返回 1。
SREM
SREM key member [member...]
- 移除集合
key
中的一个或多个member
元素。 - 如果
member
元素不存在于集合中,则忽略该元素。 - 返回被成功移除的元素的数量。
SINTER
SINTER key [key...]
- 交集:
A ∩ B = { x ∈ A ∣ x ∈ B } A \cap B = \{x \in A \mid x \in B\} A∩B={x∈A∣x∈B} - 返回给定所有集合的交集。
- 时间复杂度为 O(M * N),M 为所有给定集合中最小集合的元素数量,N 为所有给定集合中最大集合的元素数量。
SINTERSTORE
SINTERSTORE destination key [key...]
- 将所有给定集合的交集存储在集合
destination
中。 - 如果
destination
集合已经存在,则先移除该集合中的所有元素。 - 返回存储在
destination
集合中的元素数量。
SUNION
SUNION key [key...]
- 并集:
A ∪ B = { x ∣ x ∈ A ∨ x ∈ B } A\cup B = \{x\mid x\in A \vee x\in B\} A∪B={x∣x∈A∨x∈B} - 返回给定所有集合的并集。
- 时间复杂度为 O(N),N 就是总的元素数量。
SUNIONSTORE
SUNIONSTORE destination key [key...]
- 将所有给定集合的并集存储在集合
destination
中。 - 如果
destination
集合已经存在,则先移除该集合中的所有元素。 - 返回存储在
destination
集合中的元素数量。
SDIFF
SDIFF key [key...]
- 差集:
A − B = { x ∈ A ∣ x ∉ B } B − A = { x ∈ B ∣ x ∉ A } A - B = \{x \in A \mid x \notin B\} \\ B - A = \{x \in B \mid x \notin A\} A−B={x∈A∣x∈/B}B−A={x∈B∣x∈/A} - 返回给定所有集合的差集。
- 时间复杂度为 O(N),N 就是总的元素数量。
SDIFFSTORE
SDIFFSTORE destination key [key...]
- 将所有给定集合的差集存储在集合
destination
中。 - 如果
destination
集合已经存在,则先移除该集合中的所有元素。 - 返回存储在
destination
集合中的元素数量。
set编码方式
- set 类型有两种编码方式:
intset
和hashtable
。 intset
:当集合中元素都是整数并且元素数量较少时,Redis 会使用intset
编码方式。hashtable
:当集合中元素数量较多或者值不全为整数时,Redis 会使用hashtable
编码方式。
set应用场景
- 保存用户一些 “标签”,也就是用户画像,如兴趣爱好、收藏的文章、喜欢的电影等。
- 利用 set 的交集功能,可以找到两个用户共同喜欢的电影、共同的好友等。
- 使用 set 统计
UV
、PV
等指标。UV
就是user view
的简写,即用户访问某个页面的次数。PV
就是page view
的简写,即某个页面的访问次数。
Zset类型基本介绍
Zset
为有序集合,该集合为有序集合,可以存储多个不同的数据类型,包括字符串、整数、浮点数等。
与 set
,Zset
中的元素是按照顺序存放的,其通过存储 二元组<memeber, score>
,随即按照 score 对元素进行升序排序(默认为升序)。
如果出现相同的 score
,则按照 member
的字典序进行排序。
Zset
中的 member 必须是唯一的,不可重复,但是 score 可以重复。
Zset类型常用命令
ZADD
ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member...]
ZADD
命令用于向有序集合key
中添加元素。score
是一个浮点数,用于对元素member
进行排序。- 时间复杂度为
O(log(N))
,其中 N 为有序集合元素的个数。 - 返回值为成功添加的元素的数量。只是新增元素的数量,如果是更新对应的
score
值,则不会添加到计数中。 NX
:只在元素的 score 值不存在时,才执行添加操作,否则添加失败。XX
:只在元素的 score 值存在时,才执行添加操作,否则添加失败。GT
:表示当更新的member
的值已经存在并且设置的 新score
大于已经存在的score
时,才执行更新操作。如果member
不存在,也不影响添加新的memeber
。LT
:当更新的member
的值已经存在并且设置的 新score
小于已经存在的score
时,才执行更新操作。如果member
不存在,也不影响添加新的memeber
。CH
:更改返回值的数量,如果设置为CH
,则返回添加或更新元素的数量。默认是包括更新元素的数量的。INCR
:将member
的score
加上score
,返回值为新的score
值。
ZRANGE
ZRANGE key start stop [BYSCORE | BYLEX] [REV] [LIMIT offset count] [WITHSCORES]
- 返回有序集合
key
中指定区间内的元素,区间以start
和stop
指定。默认是以下标(排序好了)进行获取。start
和stop
默认都是闭区间,若写成(start (stop
表示都是开区间。 - 时间复杂度为
O(log(N)+M)
,其中 N 为有序集合元素的个数,M 为要返回的元素的个数。 REV
:表示reverse
,即按照降序进行排序,若score
相同,则按照字典序进行降序排序。BYSCORE
:表示按照score
进行排序,start
和stop
写成对应的分数区间而不是下标区间。BYLEX
:表示按照字典序进行排序,start
和stop
写成字母。其中,字母必须加上[
或者(
,如:[a [z
。写成-
和+
表示获取所有元素,类似于默认的0
和-1
。LIMIT
:限制返回元素的数量,offset
表示偏移量,count
表示数量。WITHSCORES
:表示返回元素的所有信息,即包括score
值。
ZREVRANGE、ZRANGEBYSCORE、ZREVRANGEBYSCORE、ZRANGEBYLEX、ZREVRANGEBYLEX
ZREVRANGE key start stop [WITHSCORES]
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]
ZRANGEBYLEX key min max [LIMIT offset count]
ZREVRANGEBYLEX key max min [LIMIT offset count]
- 在 6.2.0 版本之后,这些命令都将被废弃,因为
ZRANGE
命令可以实现相同的功能。
ZCARD
ZCARD key
- 返回有序集合
key
中元素的数量。 - 时间复杂度为 O(1)。
ZCOUNT
ZCOUNT key min max
- 返回有序集合
key
中指定分数区间[min, max]
内元素的数量。 - 时间复杂度为 O(log(N))。
- 也可以写成
(min (max
表示分数区间都为开区间。inf
为无穷大,-inf
为负无穷大。
ZPOPMAX
ZPOPMAX key [count]
- 移除并返回有序集合
key
中分数最高的元素,如果不写count
参数,则随机移除并返回一个元素。否则随机移除并返回count
个元素。 - 时间复杂度为
O(log(N)M)
,其中 N 为有序集合元素的个数,M 为要返回的元素的个数。 - 实际上,该命令的时间复杂度可以优化为 O(log(N)),但是 Redis 并没有实现该优化,可能是因为优化之后提升的效率并不明显。
ZPOPMIN
ZPOPMIN key [count]
- 移除并返回有序集合
key
中分数最低的元素,如果不写count
参数,则随机移除并返回一个元素。否则随机移除并返回count
个元素。 - 时间复杂度为
O(log(N)*M)
,其中 N 为有序集合元素的个数,M 为要返回的元素的个数。
BZPOPMAX、BZPOPMIN
BZPOPMAX key [key ...] timeout
BZPOPMIN key [key ...] timeout
- 阻塞式的
ZPOPMAX
和ZPOPMIN
,如果key
中为空,则阻塞timeout
时间后。在指定的时间内,如果有元素被添加到有序集合key
中,则返回该元素。 - 如果没有元素被添加到有序集合
key
中,则在指定的时间内一直阻塞,直到有元素被添加到有序集合key
中。 - 时间复杂度为
O(log(N))
,其中 N 为有序集合元素的个数。
ZRANK
ZRANK key member
- 返回有序集合
key
中member
元素的排名(从 0 开始),如果member
不存在,则返回nil
。 - 时间复杂度为
O(log(N))
。
ZREVRANK
ZREVRANK key member
- 返回有序集合
key
中member
元素的排名(从 0 开始),但是反着算,因为reverse
了。 - 时间复杂度为
O(log(N))
。
ZSCORE
ZSCORE key member
- 返回有序集合
key
中member
元素的score
值,如果member
不存在,则返回nil
。 - 时间复杂度为
O(log(1))
。
ZREM
ZREM key member [member ...]
- 从有序集合
key
中移除member
元素,如果member
不存在,则忽略。 - 返回被移除元素的数量。
- 时间复杂度为
O(M*log(N))
,其中 M 参数中元素的个数,N 为有序集合元素的个数。
ZREMRANGEBYSCORE
ZREMRANGEBYSCORE key min max
- 从有序集合
key
中移除score
值在[min, max]
区间内的元素。 - 返回被移除元素的数量。
- 时间复杂度为
O(log(N)+M)
,其中 N 为有序集合元素的个数,M 为移除的元素的个数。
ZREMRANGEBYLEX
ZREMRANGEBYLEX key min max
- 从有序集合
key
中移除member
值在[min, max]
区间内的元素。 - 返回被移除元素的数量。
- 时间复杂度为
O(log(N)+M)
,其中 N 为有序集合元素的个数,M 为移除的元素的个数。
ZREMRANGEBYRANK
ZREMRANGEBYRANK key start stop
- 从有序集合
key
中移除排名在[start, stop]
区间内的元素。 - 返回被移除元素的数量。
- 时间复杂度为
O(log(N)+M)
,其中 N 为有序集合元素的个数,M 为移除的元素的个数。
ZINCYBY
ZINCRBY key increment member
- 将
member
元素的score
值增加increment
,如果member
不存在,则添加member
元素并设置score
为increment
。 - 返回更新后的
member
元素的score
值。 - 时间复杂度为
O(log(N))
,其中 N 为有序集合元素的个数。
ZINTER
ZINTER numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM | MIN | MAX] [WITHSCORES]
- 计算多个有序集合的交集,将计算后的结果返回
numkeys
:表示需要计算交集的有序集合的个数。这里作用就有点像HTTP
协议中的content-length
。WEIGHTS
:表示为相应的key
设置权重,权重的个数必须与numkeys
相等。此处指定的相当于一个系数,会乘以当前的score
并返回。AGGREGATE
:Zset
的交集计算只是按照member
进行的,所以会存在相同member
但是score
不同的情况,此时需要对结果进行聚合。SUM
表示对score
进行求和,MIN
表示取最小的score
,MAX
表示取最大的score
。WITHSCORES
:表示返回结果中包含score
值。- 时间复杂度为
O(N*K)+O(M*log(M))
,其中 N 为所有有序集合中最小的那个,K 为需要计算交集的有序集合的个数,M 为结果集的元素个数。 - 实际上,时间复杂度可以近似看为
O(M*log(M))
。
ZINTERSTORE
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight[weight ...]] [AGGREGATE <SUM | MIN | MAX>]
- 将多个有序集合的交集存储到新的有序集合
destination
中。 - 如果
destination
已存在,则会将其重写。 - 其他的与
ZINTER
命令相同。 - 时间复杂度为
O(N*K)+O(M*log(M))
。
ZUNION
ZUNION numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM | MIN | MAX] [WITHSCORES]
- 计算多个有序集合的并集,将计算后的结果返回。
- 与
ZINTER
命令类似,只是计算的是并集。 - 时间复杂度为
O(N)+O(M*log(M))
,其中 N 为所有有序集合元素数量的总和,M 为结果集的元素个数。 - 实际上,时间复杂度也可以近似看为
O(M*log(M))
。
ZUNIONSTORE
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight[weight ...]] [AGGREGATE <SUM | MIN | MAX>]
- 将多个有序集合的并集存储到新的有序集合
destination
中。 - 如果
destination
已存在,则会将其重写。 - 其他的与
ZUNION
命令相同。 - 时间复杂度为
O(N)+O(M*log(M))
。
ZDIFF
ZDIFF numkeys key [key ...] [WITHSCORES]
- 计算多个有序集合的差集,将计算后的结果返回。
- 时间复杂度为
O(L + (N-K)log(N))
,L 为所有有序集合的所有元素总和,N 为第一个有序集合的元素个数,K 为结果集的元素个数。
ZDIFFSTORE
ZDIFFSTORE destination numkeys key [key ...]
- 将多个有序集合的差集存储到新的有序集合
destination
中。 - 如果
destination
已存在,则会将其重写。 - 时间复杂度为
O(L + (N-K)log(N))
。
Zset编码方式
Zset
类型有两种编码方式:ziplist
和skiplist
。ziplist
:当Zset
中元素数量较少或者某个元素的长度超过一定的限制时,Redis 会使用ziplist
编码方式。skiplist
:跳表,就是一种复杂链表,查询元素的时间复杂度为O(log(N))
。
Zset的应用场景
- 排行榜:比如,一个社交网站的用户排行榜,可以用
Zset
实现。 - 热度排行榜通常由多种因素影响,比如浏览量、点赞数、评论数等,可以用 多个
Zset
存储,然后用ZUNIONSTORE
或者ZINTERSTORE
并且指定不同的数值的权重(WEIGHTS),计算出一个综合的热度排行榜。