前言
我们都知道 Redis 提供了丰富的数据类型,常见的有五种:String(字符串),Hash(哈希),List(列表),Set(集合)、Zset(有序集合)。
今天我们就来详细的聊聊 Redis 这五大常见的数据类型之一 Set
;
结构类型 | 结构存储的值 | 结构读写能力 |
---|---|---|
Set | 包含字符串的无序集合; | 字符串的集合,基础方法有判断存在,添加,获取,删除,以及计算交集,并集,差集等; |
应用场景:聚合计算(并集、交集、差集)场景,比如点赞、共同关注、抽奖活动等;
概述简介
Set
类型是一个无序并唯一的键值集合,它的存储顺序不会按照插入的先后顺序进行存储。
一个集合最多可以存储 2^32-1
个元素。概念和数学中个的集合基本类似,可以交集,并集,差集等等,所以 Set
类型除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集。
Set
类型和 List
类型的区别如下:
List
可以存储重复元素,Set
只能存储非重复元素;List
是按照元素的先后顺序存储元素的,而Set
则是无序方式存储元素的。
内部实现
Set
类型的底层数据结构是由哈希表或整数集合实现的:
- 如果集合中的元素都是整数且元素个数小于
512
(默认值,set-maxintset-entries
配置)个,Redis 会使用整数集合作为Set
类型的底层数据结构; - 如果集合中的元素不满足上面条件,则 Redis 使用哈希表作为
Set
类型的底层数据结构。
常用命令
Set
常用操作:
# 往集合 key 中存入元素,元素存在则忽略,若 key 不存在则新建
# SADD key member [member ...]
127.0.0.1:6379> SADD sid10t 唱 跳 RAP
(integer) 3
# 从集合 key 中删除元素
# SREM key member [member ...]
127.0.0.1:6379> SREM sid10t RAP
(integer) 1
# 获取集合 key 中所有元素
# SMEMBERS key
127.0.0.1:6379> SMEMBERS sid10t
1) "xe8xb7xb3"
2) "xe5x94xb1"
# 获取集合key中的元素个数
# SCARD key
127.0.0.1:6379> SCARD sid10t
(integer) 2
# 判断 member 元素是否存在于集合 key 中
# SISMEMBER key member
127.0.0.1:6379> SISMEMBER sid10t rap
(integer) 0
# 从集合 key 中随机选出 count 个元素,元素不从 key 中删除
# SRANDMEMBER key [count]
127.0.0.1:6379> SRANDMEMBER sid10t 1
1) "xe8xb7xb3"
# 从集合 key 中随机选出 count 个元素,元素从 key 中删除
SPOP key [count]
127.0.0.1:6379> SPOP sid10t 2
1) "xe5x94xb1"
2) "xe8xb7xb3"
# 将一个指定的值,移动到另外一个 set 集合;
# SMOVE source destination member
127.0.0.1:6379> SMOVE sid10t ikun rap
(integer) 1
127.0.0.1:6379> SMEMBERS ikun
1) "rap"
Set
运算操作:
# 交集运算
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
做聚合计算(交集、差集、并集)时导致主库被阻塞,我们可以选择一个从库完成聚合统计,或者把数据返回给客户端,由客户端来完成聚合统计。
点赞
Set
类型可以保证一个用户只能点一个赞,这里举例一个场景,key 是文章 id,value 是用户 id。
uid:1
、uid:2
、uid:3
三个用户分别对 article:1 文章点赞了。
# 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 文章所有点赞用户 :
代码语言:javascript复制> SMEMBERS article:1
1) "uid:3"
2) "uid:2"
获取 article:1 文章的点赞用户数量:
代码语言:javascript复制> SCARD article:1
(integer) 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,uid:2
用户关注公众号 id 为 7、8、9、10、11。
# 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
uid:1
和 uid:2
共同关注的公众号:
# 获取共同关注
> SINTER uid:1 uid:2
1) "7"
2) "8"
3) "9"
给 uid:2
推荐 uid:1
关注的公众号:
> SDIFF uid:1 uid:2
1) "5"
2) "6"
验证某个公众号是否同时被 uid:1
或 uid:2
关注:
> SISMEMBER uid:1 5
(integer) 1 # 返回1,说明关注了
> SISMEMBER uid:2 5
(integer) 0 # 返回0,说明没关注
抽奖活动
存储某活动中中奖的用户名 ,Set
类型因为有去重功能,可以保证同一个用户不会中奖两次。
key 为抽奖活动名,value 为员工名称,把所有员工名称放入抽奖箱:
代码语言:javascript复制>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"
后记
Redis 五大常见数据类型之一的 Set
就先讲到这里了,后续还会有其他类型的讲解呢,敬请关注!
参考资料:
- 《Redis 核心技术与实战》
- 一文回顾 Redis 五大对象 (数据类型)
- 谈谈Redis五种数据结构及真实应用场景
- Redis的数据结构与应用场景
- Redis 常见数据类型和应用场景