Redis-Set

悲观者从机会中看到困难。乐观者从困难中看到机会。
——温斯顿·丘吉尔

Set 类型是一个无序并唯一的键值集合,它的存储顺序不会按照插入的先后顺序进行存储。
一个集合最多可以存储 2^32-1 个元素。概念和数学中个的集合基本类似,可以交集,并集,差集等等,所以 Set 类型除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集。

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

  • List可以存储重复元素,Set只能存储非重复元素;
  • List是按照元素的先后顺序存储元素的,而Set则是无序方式存储元素的。

内部实现

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

  • 如果集合中的元素都是整数且元素个数小于 512(默认值,set-maxintset-entries 配置)个Redis 会使用整数集合作为 Set 类型的底层数据结构;
  • 如果集合中的元素不满足上面条件,则 Redis 使用哈希表作为 Set 类型的底层数据结构。

应用场景

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

因此 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

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则说明点赞了

共同关注

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 # 返回0,说明关注了
> SISMEMBER uid:2 5
(integer)0 # 返回0,说明没关注

抽奖活动

存储某活动中中奖的用户名 ,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"

原文

posted @ 2025-04-06 16:11  Tsukinor  阅读(38)  评论(0)    收藏  举报