04- Redis 中的 Set 数据类型和应用场景

1. 介绍

Set 类型是一个无序并唯一的键值集合,它的存储顺序不会按照插入的先后顺序进行存储。

一个集合最多可以存储 2^32-1 个元素。概念和数学中的集合基本类似,可以交集、并集、差集等,所以 Set 类型除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集。

Set 类型和 List 类型的区别如下:

  • List 可以存储重复元素,Set 只能存储非重复元素;

  • List 是按照元素的先后顺序存储元素的,而 Set 则是无序方式存储元素的。

2. 内部实现

Set 类型的底层数据结构是由哈希表或整数集合实现的;

  • 如果集合中的元素都是整数且元素个数小于 512 (默认值, set-maxintset-entries 配置)个,Redis 会使用整数集合作为 Set 类型的底层数据结构;

  • 如果集合中的元素不满足上面条件,则 Redis 使用哈希表作为 Set 类型的底层数据结构。

3. 常用命令

Set 常用操作:

# 往集合 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]

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 ...]

4. 应用场景

集合的主要几个特性,无序、不可重复、支持并交差等操作。

因此 Set 类型比较适合用来数据去重和保障数据的唯一性,还可以用来统计多个集合的交集、错集和并集等,当我们存储的数据是无序并且需要去重的情况下,比较适合使用集合类型进行存储。

但是要提醒一下,这里有一个潜在的风险。Set 的差集、并集、交集的计算复杂度较高,在数据量较大的情况下,如果直接执行这些计算,会导致 Redis 示例阻塞

在主从集群中,为了避免主库因为 Set 做聚合计算(交集、差集、并集)时导致主库被阻塞,我们可以选择一个从库完成聚合统计,或者把数据返回给客户端,由客户端来完成聚合统计。

4.1 点赞

Set 类型可以保证一个用户只能点一个赞,这里举例子一个场景,key 是文章id,value 是用户 id。

uid:1uid:2uid: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 文章所有点赞用户:

> SMEMBERS article:1
1) "uid:3"
2) "uid:2"

获取 article:1 文章的点赞用户数量:

> SCARD article:1
(integer) 2

判断用户uid:1是否对文章 article:1 点赞了:

> SISMEMBER article:1 uid:1
(integer) 0  # 返回 0 说明没点赞,返回 1 则说明点赞了

4.2 共同关注

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:1 7 8 9 10 11
(integer) 5

uid:1uid: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:1uid:2 关注:

> SISMEMBER uid:1 5
(integer) 1  # 返回 1,说明关注了
​
> SISMEMBER uid:2 5
(integer) 0  # 返回 0,说明没关注

4.3 抽奖活动

存储某活动中中奖的用户名,Set 类型因为有去重功能,可以保证同一个用户不会中奖两次。

key 为抽奖活动名,value 为员工名称,把所有员工名称放入抽奖箱:

> SADD lucky Tom Jerry 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"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值