介绍
Set(集合)是一个无序并唯一的值集合,一个集合最多可以存储 2^32-1
个元素
Set 类型除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集等聚合计算
Set 和 List 的区别
- List 可以存储重复元素,Set 只能存储非重复元素
- List 是按照元素的先后顺序存储元素的,而 Set 则是无序方式存储元素的
内部实现
- 如果集合中的元素都是整数且元素个数小于 512 (默认值,
set-maxintset-entries
配置)个,使用整数集合 - 否则,使用哈希表
常用命令
增删改查:
# 往集合 key 中存入元素,元素存在则忽略,若 key 不存在则新建
SADD key member [member ...]
# 从集合 key 中删除元素
SREM key member [member ...]
# 获取集合 key 中所有元素
SMEMBERS key
# 获取集合 key 中的元素个数
SCARD key
# 判断 member 元素是否存在于集合 key 中
SISMEMBER key member
# 从集合 key 中随机选出 count 个元素,元素不从 key 中删除
SRANDMEMBER key [count]
# 从集合 key 中随机选出 count 个元素,元素从 key 中删除
SPOP key [count]
聚合计算:
# 交集运算
SINTER key [key ...]
# 将交集结果存入新集合 destination 中
SINTERSTORE destination key [key ...]
# 并集运算
SUNION key [key ...]
# 将并集结果存入新集合 destination 中
SUNIONSTORE destination key [key ...]
# 差集运算
SDIFF key [key ...]
# 将差集结果存入新集合 destination 中
SDIFFSTORE destination key [key ...]
应用场景
集合的主要几个特性,无序、不可重复、支持并交差等操作
因此 Set 类型比较适合用来数据去重和保障数据的唯一性,还可以用来统计多个集合的交集、差集和并集等
注意:Set 的差集、并集和交集的计算复杂度较高,在数据量较大的情况下,可能导致 Redis 实例阻塞
在主从集群中,为了避免主库被阻塞,可以选择一个从库完成聚合统计,或者把数据返回给客户端,由客户端完成聚合统计
点赞
Set 类型可以保证一个用户只能点一个赞
例如,key 是文章 id,value 是用户 id:
# uid:1 用户对文章 article:1 点赞
> SADD article:1 uid:1
(integer) 1
# uid:2 用户对文章 article:1 点赞
> SADD article:1 uid:2
(integer) 1
# uid:3 用户对文章 article:1 点赞
> SADD article:1 uid:3
(integer) 1
# uid:1 取消了对 article:1 文章点赞
> SREM article:1 uid:1
(integer) 1
# 获取 article:1 文章的点赞用户数量
> SCARD article:1
(integer) 2
# 获取 article:1 文章所有点赞用户
> SMEMBERS article:1
1) "uid:3"
2) "uid:2"
# 判断用户 uid:1 是否对文章 article:1 点赞了
> SISMEMBER article:1 uid:1
(integer) 0 # 返回 0 说明没点赞,返回 1 则说明点赞了
共同关注
Set 类型支持交集运算,所以可以用来计算共同关注的好友、公众号等
例如,key 是用户 id,value 是已关注公众号的 id:
# uid:1 用户关注公众号 id 为 5、6、7、8、9
> SADD uid:1 5 6 7 8 9
(integer) 5
# uid:2 用户关注公众号 id 为 7、8、9、10、11
> SADD uid:2 7 8 9 10 11
(integer) 5
# 获取共同关注
> SINTER uid:1 uid:2
1) "7"
2) "8"
3) "9"
# 给 uid:2 推荐 uid:1 关注的公众号
> SDIFF uid:1 uid:2
1) "5"
2) "6"
抽奖活动
存储某活动中中奖的用户名,Set 类型有去重功能,可以保证同一个用户最多中奖一次
例如,key 为抽奖活动名,value 为员工名:
# 把所有员工名称放入抽奖箱
> SADD lucky Tom Jerry John Sean Marry Lindy Sary Mark
(integer) 5
# 如果允许重复中奖,可以使用 SRANDMEMBER 命令
# 抽取 1 个一等奖
> SRANDMEMBER lucky 1
1) "Tom"
# 抽取 2 个二等奖
> SRANDMEMBER lucky 2
1) "Mark"
2) "Jerry"
# 抽取 3 个三等奖
> SRANDMEMBER lucky 3
1) "Sary"
2) "Tom"
3) "Jerry"
# 如果不允许重复中奖,可以使用 SPOP 命令
# 抽取 1 个一等奖
> SPOP lucky 1
1) "Sary"
# 抽取 2 个二等奖
> SPOP lucky 2
1) "Jerry"
2) "Mark"
# 抽取 3 个三等奖
> SPOP lucky 3
1) "John"
2) "Sean"
3) "Lindy"