[TOC] #### 1. 前言 --- 你在微博上关注了一堆人,你朋友也关注了一堆人,你想看看你们共同关注了谁,怎么做 ? 遍历你的关注列表,一个个去他列表里查 ? 数据量大了,这个写法能把数据库跑挂,Redis 的 Set 一行命令搞定 #### 2. Set 特点 --- Set 的特点:无序、不重复 往里面加重复的元素,自动过滤: ```bash sadd tags python java go python smembers tags # 只有3个,python去重了 ``` 集合运算(核心能力) ```bash sadd user:1:follow A B C D sadd user:2:follow B C E F sinter user:1:follow user:2:follow # 交集 → B C(共同关注) sunion user:1:follow user:2:follow # 并集 → A B C D E F(所有关注) sdiff user:1:follow user:2:follow # 差集 → A D(user:1 关注的,但 user:2 没关注的) ``` 共同好友就是 `sinter` 一行命令,不用写循环,不用遍历,Redis 内部用哈希表实现,效率很高 #### 3. 应用场景 --- 抽奖系统:年会抽奖,每人只能中一次 ```bash sadd lottery:2026 zhangsan lisi wangwu zhaoliu spop lottery:2026 # 随机抽一个,抽完就移除了 ``` `spop` 会把元素删掉,所以不会重复中奖,如果只是看看不移除,用 `srandmember` ```bash # 随机抽取 2 个数据 srandmember lottery:2026 2 ``` 标签系统:文章打标签(给用户推荐兴趣相似的文章,也是这个思路) ```bash sadd article:1001:tags mysql redis java sadd article:1002:tags mysql python go sinter article:1001:tags article:1002:tags # 共同标签 → mysql ``` UV 统计:统计一篇文章有多少独立访客 ```bash sadd article:1001:uv user_001 sadd article:1001:uv user_002 sadd article:1001:uv user_001 # 重复访问,自动去重 scard article:1001:uv # 获取集合中的元素个数(2) ``` 不过 UV 量大的时候 Set 占内存,第 13 讲会讲 HyperLogLog,更省空间 底层编码 + 全是整数且数量少 → intset,连续内存,效率高 + 其它情况 → hashtable,O(1) 查找 #### 4. 本文小结 --- 小总结: + Set 无序、不重复 + 核心能力:交集、并集、差集 + 共同好友 = 交集,抽奖 = spop,标签 = Set + 交集 + UV 统计可以用 Set,量大考虑 HyperLogLog