2.5 集合 Set
Set 是一个无序、自动去重的集合,还支持交集、并集、差集运算。抽奖、点赞、共同好友都靠它。
1. Set 是什么
和数学课上的"集合"概念一样:
- 不重复:同一个值塞两次,只会保留一个
- 无序:不保证任何顺序(这是它和 List 的最大区别)
- 支持集合间运算:交集(都有)、并集(合并)、差集(我有你没有)
2. 基础操作
Set 命令以 s 开头:
# 添加元素(重复的自动忽略,返回实际新增个数)
127.0.0.1:6379> sadd tags "科技" "编程" "科技"
(integer) 2 # "科技"重复,只加入了 2 个
# 查看所有元素
127.0.0.1:6379> smembers tags
1) "编程"
2) "科技"
# 判断元素是否存在(超快,O(1))
127.0.0.1:6379> sismember tags "科技"
(integer) 1
127.0.0.1:6379> sismember tags "美食"
(integer) 0
# 元素个数
127.0.0.1:6379> scard tags
(integer) 2
# 删除元素
127.0.0.1:6379> srem tags "编程"
(integer) 1
3. 随机相关命令(抽奖必备)
127.0.0.1:6379> sadd lottery 用户A 用户B 用户C 用户D 用户E
(integer) 5
# 随机看 2 个(不删除)—— 适合"可重复中奖"的抽奖
127.0.0.1:6379> srandmember lottery 2
1) "用户C"
2) "用户A"
# 随机弹出 1 个(取出并删除)—— 适合"不可重复中奖"的抽奖
127.0.0.1:6379> spop lottery
"用户D"
127.0.0.1:6379> scard lottery
(integer) 4 # 用户D 已经不在池子里了
4. 集合运算(Set 的独门绝技)
准备数据——两个人的好友列表:
127.0.0.1:6379> sadd friends:小明 小红 小刚 小丽
(integer) 3
127.0.0.1:6379> sadd friends:小华 小红 小丽 小强
(integer) 3
# 交集:共同好友
127.0.0.1:6379> sinter friends:小明 friends:小华
1) "小红"
2) "小丽"
# 并集:两人的好友合并(去重)
127.0.0.1:6379> sunion friends:小明 friends:小华
1) "小红"
2) "小刚"
3) "小丽"
4) "小强"
# 差集:小明有、小华没有的好友(注意顺序有影响)
127.0.0.1:6379> sdiff friends:小明 friends:小华
1) "小刚"
# 把运算结果存到新 key(store 系列)
127.0.0.1:6379> sinterstore common:xiaoming:xiaohua friends:小明 friends:小华
(integer) 2
5. 典型应用场景
场景一:点赞 / 收藏(天然防重复)
# 用户 1001 给文章 55 点赞
sadd article:55:likes 1001
# 重复点赞?没关系,Set 自动去重,返回 0 表示没有新增
sadd article:55:likes 1001 # → 0
# 取消点赞
srem article:55:likes 1001
# 点赞总数
scard article:55:likes
# 判断当前用户是否已点赞(前端展示红心用)
sismember article:55:likes 1001
场景二:抽奖
sadd lottery:2026 用户1 用户2 ... 用户N # 报名进池
spop lottery:2026 3 # 抽 3 名一等奖(中奖后移出池子)
场景三:共同好友 / 可能认识的人
sinter friends:A friends:B # 共同好友
sdiff friends:B friends:A # B 的好友里 A 还不认识的 → "可能认识的人"推荐
场景四:每日独立访客统计(UV)
sadd uv:2026-07-26 用户1001 # 同一用户当天访问多少次都只记一个
scard uv:2026-07-26 # 今天的独立访客数
💡 如果用户量上亿,Set 会很占内存,这时用 HyperLogLog(第 06 章介绍)。
6. Set vs List 怎么选
| 需求 | 选择 |
|---|---|
| 需要保持插入顺序 / 允许重复 | List |
| 需要去重 / 判断"在不在" / 集合运算 | Set |
| 既要去重又要排序 | ZSet(下一章) |
7. 动手练习
- 建立
article:1:likes,让用户 100、200、300 点赞,再让 100 重复点赞一次,用scard确认总数是 3 - 判断用户 200 是否点过赞、用户 999 是否点过赞
- 建立两个班级的选修课名单
course:python和course:java,各放几个学生(有重叠),求:两门都选的、至少选了一门的、只选 Python 的 - 用
spop从任意 Set 里模拟一次抽奖
8. 小结
| 命令 | 作用 |
|---|---|
sadd / srem | 添加 / 删除 |
smembers / scard | 查看全部 / 计数 |
sismember | 判断是否存在 |
srandmember / spop | 随机取(不删 / 删) |
sinter / sunion / sdiff | 交 / 并 / 差集 |
记住 Set 的三大绝活:去重、判存在、集合运算。
下一章:自带排序的排行榜神器 👉 2.6 有序集合 ZSet