目录
1. 特点
集合类型也是保存多个字符串类型的元素的,和 list 类型不同的是:
- 无序性:集合中的元素没有顺序。
- 唯一性:集合中的元素不允许重复。
容量:一个集合最多可以存储 (2^{32} - 1) 个元素。
- Redis除了⽀持集合内的增删查改操作,同时还⽀持多个集合取交集、并集、差集,合理地使⽤好集合类型,能在实际开发中解决很多问题
- set 中的元素,叫做 member
2. 常用命令
2.1 普通命令
SADD
- 描述:将一个或多个元素添加到集合中。
- 语法:
SADD key member [member ...]
- 时间复杂度:O(1)
- 返回值:本次添加成功的元素个数。
- 示例:
redis> SADD myset "Hello"
(integer) 1
redis> SADD myset "World"
(integer) 1
redis> SADD myset "World"
(integer) 0
第一次sadd
,set1
不存在,此时创建集合并且插入1 2 3
,返回3
表示成功插入三个数字。第二次sadd
,由于数字2 3
已经存在,所以只插入了4 5
,返回2
表示成功插入两个元素。
SMEMBERS
- 描述:获取集合中的所有元素。
- 语法:
SMEMBERS key
- 时间复杂度:O(N)
- 返回值:所有元素的列表。
- 示例:
redis> SMEMBERS myset
1) "Hello"
2) "World"
S IS MEMBER
- 描述:判断一个元素是否在集合中。
- 语法:
SISMEMBER key member
- 时间复杂度:O(1)
- 返回值:1 表示元素在集合中,0 表示不在或 key 不存在。
- 示例:
redis> SISMEMBER myset "one"
(integer) 1
redis> SISMEMBER myset "two"
(integer) 0
SCARD
-
- 描述:获取集合的基数(元素个数)。
- 语法:
SCARD key
- 时间复杂度:O(1)
- 返回值:集合中的元素个数。
- 示例:
redis> SCARD myset
(integer) 2
SPOP
-
- 描述:从集合中删除并返回一个或多个元素。
- 语法:
SPOP key [count]
- 时间复杂度:O(N),N 是 count
- 返回值:取出的元素。
- 注意:由于
set
内的元素是⽆序的,所以取出哪个元素实际是未定义⾏为,即可以看作随机的 - 示例:
redis> SPOP myset
"one"
redis> SPOP myset 3
1) "three"
2) "four"
3) "two"
官方文档中声明,spop
得到的值是随机的,就算是两个相同的集合,同样的操作得到的值也不一样。因为Redis
源码中给spop
增加了一个生成随机成员的过程,是真正做了随机功能。
SRANDMEMBER
- 获取
set
中的随即元素
srandmember key [count]
返回随机获取到的元素,count
表示要获取的元素个数。
、
SMOVE
-
- 描述:将一个元素从源集合移动到目标集合。
- 语法:
SMOVE source destination member
- 时间复杂度:O(1)
- 返回值:1 表示移动成功,0 表示失败。
- 示例:
redis> SMOVE myset myotherset "two"
(integer) 1
此处将set2
中的666
元素移动到了set1
中。
在移动过程中,可能出现以下两种情况:
member
已经在destination
中存在,此时会将member
从source
中删除,并且spop
返回1
视为移动成功member
在source
中不存在,此时spop
返回0
,表示移动失败
SREM
-
- 描述:将指定的元素从集合中删除。
- 语法:
SREM key member [member ...]
- 时间复杂度:O(N),N 是要删除的元素个数。
- 返回值:本次操作删除的元素个数。
- 示例:
redis> SREM myset "one"
(integer) 1
2.2 集合间操作
除了基本的集合命令,Redis
还提供了集合之间的一些命令。
set
支持交集(inter
)、并集(union
)、差集(diff
)
- SINTER
-
- 描述:获取给定集合的交集。
- 语法:
SINTER key [key ...]
- 时间复杂度:O(N * M),N 是 最小的集合元素个数,M 是最大的集合元素个数。
- 返回值:交集的元素。
- 示例:
redis> SINTER key1 key2
1) "c"
- SINTER STORE
-
- 描述:获取给定集合的交集 并保存到目标集合中。
- 语法:
SINTERSTORE destination key [key ...]
- 时间复杂度:O(N * M),N 是最小的集合元素个数,M 是最大的集合元素个数。
- 返回值:交集的元素个数。
- 示例:
redis> SINTERSTORE key key1 key2
(integer) 1
此处将set1
和set2
的交集输出到set4
中,sinterstore
返回3
表示交集有三个元素。
- SUNION
-
- 描述:获取给定集合的并集。
- 语法:
SUNION key [key ...]
- 时间复杂度:O(N),N 是给定的所有集合的总元素个数。
- 返回值:并集的元素。
- 示例:
redis> SUNION key1 key2
1) "a"
2) "c"
3) "e"
4) "b"
5) "d"
- SUNION STORE
-
- 描述:获取给定集合的并集 并保存到目标集合中。
- 语法:
SUNIONSTORE destination key [key ...]
- 时间复杂度:O(N),N 是给定的所有集合的总元素个数。
- 返回值:并集的元素个数。
- 示例:
redis> SUNIONSTORE key key1 key2
(integer) 5
- SDIFF
-
- 描述:获取给定集合的差集。
- 语法:
SDIFF key [key ...]
- 时间复杂度:O(N),N 是给定的所有集合的总元素个数。
- 返回值:差集的元素。
- 示例:
redis> SDIFF key1 key2
1) "a"
2) "b"
- SDIFFSTORE
-
- 描述:获取给定集合的差集 并保存到目标集合中。
- 语法:
SDIFFSTORE destination key [key ...]
- 时间复杂度:O(N),N 是给定的所有集合的总元素个数。
- 返回值:差集的元素个数。
- 示例:
redis> SDIFFSTORE key key1 key2
(integer) 2
2.3. 命令小结
命令 | 时间复杂度 |
SADD key element [element ...] | O(k),k 是元素个数 |
SREM key element [element ...] | O(k),k 是元素个数 |
SCARD key | O(1) |
SISMEMBER key element | O(1) |
SRANDMEMBER key [count] | O(n),n 是 count |
SPOP key [count] | O(n),n 是 count |
SMEMBERS key | O(k),k 是元素个数 |
SINTER key [key ...] / SINTERSTORE | O(m * k),k 是几个集合中元素最少的个数,m 是键个数 |
SUNION key [key ...] / SUNIONSTORE | O(k),k 是多个集合的元素个数总和 |
SDIFF key [key ...] / SDIFFSTORE | O(k),k 是多个集合的元素个数总和 |
3.内部编码
1.intset(整数集合)
- 当集合中的元素都是整数
- 并且元素的个数⼩于set-max-intset-entries配置(默认512个)时
Redis会选⽤intset来作为集合的内部实现,从⽽减少内存的使⽤
2.hashtable(哈希表)
- 当集合类型不满足以上条件,也就是成员数量太多,或者有成员不是
int
,那么采用hashtable
哈希表来实现set
。
4. 应用场景
1. 构造用户画像
- 标签保存:平台可以通过获取用户的信息和根据用户的浏览记录来分析用户的特征,给用户打标签。
-
- 示例:分析出用户是青年,就在 set 中加入 "青年" 标签;如果是男性,加入 "男性" 标签。可以来实现 一个用户的画像
- 命令:
sadd user:1:tags "青年" "男性"
- 标签共享:如果两家公司有商业合作,可以共享用户的标签。获取到其他公司的标签后,加入到自己的标签集中,自动去重。
-
- 示例:
sadd user:1:tags tag1 tag2 tag5
sadd user:2:tags tag2 tag3 tag5
...
sadd user:k:tags tag1 tag2 tag4
- 思考:所以 我们平时看到的信息推送,其实是存在 信息茧房 的
2. 计算用户之间的共同好友
- 功能实现:QQ 等社交平台常用此功能,基于集合 求交集来实现好友推荐。
-
- 示例:A 和 B 是好友,A 和 C 是好友,B 和 C、D 是好友,系统会把 D 推荐给 A。
- 命令:
sadd user:A:friends B C
sadd user:B:friends A C D
sinter user:A:friends user:B:friends
3. 统计 UV
- 去重功能:主要用于统计独立访客数(UV),每个用户访问服务器会产生 UV,但同一用户多次访问不会增加 UV。
-
- 示例:存储在 set 中的 UV 会按用户去重。
- 命令:
sadd uv_set user1
sadd uv_set user2
sadd uv_set user1 # 不会增加 UV
scard uv_set # 获取 UV 数量
总结
- 用户画像:通过标签管理和共享,构建详细的用户画像。
- 共同好友:利用集合 求交集,推荐潜在的好友。
- UV 统计:利用集合的 去重功能,准确统计独立访客数。