Redis Set原生支持交集(SINTER)、并集(SUNION)、差集(SDIFF)和对称差集(Redis 6.2+可用SDIFF或SUNION+SINTER组合),所有运算均有STORE版本可持久化结果,且SDIFF严格按参数顺序计算,SSCAN替代SMEMBERS避免阻塞。

Redis Set 的交集、并集、差集怎么用?
Redis Set 原生支持四种核心集合运算:交集(SINTER)、并集(SUNION)、差集(SDIFF)、对称差集(SDIFF 在 Redis 6.2+ 中可直接用于两集合,或用 SUNION + SINTER 组合模拟)。这些不是“额外扩展”,而是底层哈希表结构天然支撑的原子操作。
常见错误是把 SDIFF 当成无序对比——它严格按参数顺序计算:SDIFF key1 key2 返回的是 “key1 有但 key2 没有” 的元素;反过来写结果完全不同。另外,单个 SINTER 或 SUNION 传一个 key,会直接返回该集合全部成员,不是报错。
-
SINTER key1 key2 key3:返回三个集合共有的元素(交集) -
SUNION key1 key2:合并去重后返回全部元素(并集) -
SDIFF key1 key2 key3:只保留 key1 中存在、且在 key2 和 key3 中都不存在的元素 - 对称差集没有独立命令,但
SUNION key1 key2结果减去SINTER key1 key2就是等价逻辑;Redis 6.2 起可用SDIFF key1 key2(两集合)直接得到对称差集
交集/并集/差集的结果能存到新 key 吗?
能,而且推荐这么做——尤其当结果要复用或持久化时。所有基础运算都有对应 *STORE 版本:SINTERSTORE、SUNIONSTORE、SDIFFSTORE。它们把运算结果直接写入目标 key,返回值是写入的元素数量。
注意:*STORE 命令会覆盖目标 key 的原有内容;如果目标 key 是非 Set 类型,操作会失败并报错 (error) WRONGTYPE Operation against a key holding the wrong kind of value。另外,SINTERSTORE dest key1 key2 中的 dest 不需要预先存在,Redis 会自动创建。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 使用
SINTERSTORE common_friends user_a user_b比反复调用SINTER更省带宽和 CPU - 如果目标 key 正被其他客户端读取,
*STORE是原子写入,不会出现中间态 - 不建议对超大集合(比如千万级用户标签)直接用
SMEMBERS拿结果再写入,应优先走*STORE命令完成整个流程
为什么大集合上做 SMEMBERS 很危险?
因为 SMEMBERS 是阻塞式全量读取:它一次性把整个集合加载进内存并返回所有元素。当集合含几十万甚至百万成员时,不仅拖慢当前连接,还可能触发 Redis 主线程卡顿,影响其他请求。
真正安全的做法是用 SSCAN 分批迭代。例如 SSCAN tags 0 MATCH "tech:*" COUNT 100,游标从 0 开始,每次最多取 100 个匹配 tech: 前缀的标签,直到返回游标为 0 表示遍历完成。这个过程不阻塞,适合后台任务或分页场景。
-
SSCAN不保证遍历顺序,也不承诺一次扫完所有元素(受COUNT和内部 rehash 影响),但能避免 OOM 和延迟尖刺 - 不要用
SMEMBERS做“判断集合是否为空”的逻辑——改用SCARD key,它是 O(1) 且不加载数据 - 如果业务必须拿到全部元素(比如导出),确保集合大小可控,或加监控告警:当
SCARD key> 10000 时禁止走SMEMBERS
Set 运算性能到底有多快?
单个元素的增删查确实是 O(1),但集合间运算是 O(N),N 是参与运算的所有集合元素总数。比如 SINTER key1 key2,时间复杂度 ≈ SCARD key1 + SCARD key2;SUNION 则取决于总去重后元素数。
这意味着:两个各含 100 万成员的集合求交集,实际要遍历约 200 万次哈希查找。如果并发高、集合又大,CPU 使用率会明显上升。生产环境要注意控制参与运算的集合规模。
- 提前用
SCARD评估集合大小,避免意外的大集合参与运算 - 对高频使用的交集结果(如“活跃用户 ∩ 付费用户”),用
SINTERSTORE预计算并设置 TTL,而不是每次实时算 - Redis 7.0+ 支持
SRANDMEMBER的COUNT参数上限提升,但集合运算本身没做算法优化,别指望“自动加速”
SDIFF 的参数顺序和 SSCAN 的游标管理——前者写反了逻辑就全错,后者漏处理游标会导致漏数据。别的都能调参或换方案,这两点必须写死在代码里。

















