# Redis Set 结构如何实现抽奖、共同关注等场景?

# 标准答案

Redis Set(集合)无序、去重的集合结构,支持 快速查找、随机抽取、交集并集操作,非常适用于 抽奖、共同关注、标签匹配等场景

  • 抽奖SRANDMEMBER 可随机抽取元素,SPOP 可实现不重复抽奖。
  • 共同关注SINTER 可高效计算多个用户的共同关注。
  • 标签匹配SUNION 获取多个标签的合集,SDIFF 计算差集筛选目标用户。

# 答案解析

# 1. Redis Set 结构特点

Redis 的 Set 是一个 无序、去重的集合,底层实现基于 哈希表 + 整数数组,支持 O(1) 级别的插入、删除、判断是否存在操作,同时提供 随机抽取、交集、并集、差集等集合运算,适用于 去重、随机选取、关系计算 相关场景。

常见指令:

操作 命令 说明
添加元素 SADD key member1 member2 O(1) 复杂度,向集合中添加元素
移除元素 SREM key member O(1) 复杂度,从集合中移除元素
随机抽取 SRANDMEMBER key [count] O(1),随机获取一个或多个元素
随机弹出 SPOP key [count] O(1),从集合中移除并返回一个或多个元素
交集 SINTER key1 key2 O(N) 复杂度,计算多个集合的交集
并集 SUNION key1 key2 O(N) 复杂度,计算多个集合的并集
差集 SDIFF key1 key2 O(N) 复杂度,计算 A - B 的差集
查询成员 SISMEMBER key member O(1),判断成员是否在集合中
获取大小 SCARD key O(1),获取集合元素数量

# 2. Redis Set 实现抽奖功能

# (1)单次随机抽奖

场景:从 100 万用户中 随机抽取 1 人 中奖。

SRANDMEMBER lottery_users 1
1
  • 优点:不会影响原集合,可用于 随机推荐幸运用户抽取
  • 缺点:可能会重复抽取相同用户。

# (2)不重复抽奖

场景:从 100 万用户中 抽取 10 人,保证 不会重复

SPOP lottery_users 10
1
  • 优点:抽出的用户会从集合中删除,确保不会重复中奖。
  • 缺点:破坏原集合,需事先备份数据。

📌 解决方案:若要保留用户池,可 备份数据

SUNIONSTORE lottery_backup lottery_users  # 备份原数据
SPOP lottery_backup 10  # 在副本中抽奖
1
2

# 3. Redis Set 计算共同关注

# (1)计算共同关注

场景:用户 A(关注 x、y、z),用户 B(关注 y、z、w),计算 共同关注的人

SINTER user:A user:B
1
  • 示例数据
SADD user:A "Tom" "Jerry" "Mike"
SADD user:B "Jerry" "Mike" "David"

SINTER user:A user:B  # 共同关注:["Jerry", "Mike"]
1
2
3
4
  • 优点:查询 O(N) 复杂度,比 SQL JOIN 计算更快,适合大规模用户关系计算。

# (2)计算好友推荐

场景:用户 A 和用户 B 的好友合集(即可能的好友推荐)。

SUNION user:A user:B
1

优化策略

  1. 过滤掉用户本身

    SDIFF user:A user:B
    
    1
    • 可过滤掉 user:A 关注过的好友,避免推荐已经认识的人
  2. 按活跃度排序推荐

    ZINTERSTORE common_followers 2 user:A user:B WEIGHTS 1 1
    
    1
    • 结合 Sorted Set 计数权重,推荐共同关注最多的用户

# 4. Redis Set 计算标签匹配

# (1)计算兴趣标签匹配

场景:用户 A 喜欢 篮球、足球、音乐,用户 B 喜欢 足球、音乐、电影,计算相同兴趣。

SINTER user:A_tags user:B_tags
1
  • 示例数据
SADD user:A_tags "basketball" "football" "music"
SADD user:B_tags "football" "music" "movie"

SINTER user:A_tags user:B_tags  # 结果:["football", "music"]
1
2
3
4
  • 应用场景:用于兴趣推荐、个性化匹配、社交匹配等场景。

# 5. Redis Set vs. List / Hash / Sorted Set

结构 适用场景 主要特点
Set(集合) 去重、不重复抽取、关系计算 无序、去重、高效交并集计算
List(列表) 消息队列、聊天记录 有序、允许重复、支持索引操作
Hash(哈希表) 用户信息存储 适用于存储对象,字段查找高效
Sorted Set(有序集合) 排行榜、热度排序 有序存储,可按分数排序

# 深入追问

  1. 为什么 Redis Set 适用于抽奖,而 List 不适合?
  2. SINTER 在用户量百万级时,如何优化性能?
  3. 如何用 Redis 计算相似用户推荐?
  4. SetSorted Set 在排行榜场景的区别?
  5. 如何高效存储百万级用户的兴趣标签?

# 相关面试题

  • Redis SINTER 计算共同关注的底层原理是什么?
  • SRANDMEMBERSPOP 在抽奖场景下的区别?
  • SetSorted Set 在社交应用中的不同应用场景?
  • Redis SUNION 查询合并多个标签的性能优化策略?
  • 为什么 Kafka 不使用 Redis Set 结构存储消息?

# 总结

  1. Redis Set 适用于无序去重场景**,高效支持 抽奖、共同关注、标签匹配等计算
  2. SPOP 适用于一次性抽奖**,而 SRANDMEMBER 适用于可重复抽奖**。
  3. SINTER 可高效计算共同关注**,SUNION 可合并多个集合,SDIFF 可用于排除筛选。
  4. 相比 SQL JOIN,Redis Set 计算速度快,适用于社交网络、兴趣推荐等场景。
  5. Set 不适用于有序数据(如排行榜),此时应使用 Sorted Set