Redis命令:SINTERCARD

发布时间:2026/10/25 1:59:11
Redis命令:SINTERCARD

Redis SINTERCARD 命令详细教程

SINTERCARD返回多个集合交集的成员数量,而不返回成员本身。它是 Redis 7.0.0 新增的命令,专为"只关心交集大小"的场景设计:省去把全部交集成员传输到客户端的开销,并支持LIMIT参数在达到阈值后立即停止计算。判断"两人是否有共同好友""商品是否满足全部筛选条件"时,用它比 SINTER 更省资源。

资料合集:https://pan.quark.cn/s/10e98d308913、https://pan.quark.cn/s/f56bc69c5338

一、概览与语法

SINTERCARD numkeys key [key ...] [LIMIT limit]
项目说明
数据类型Set
支持版本Redis 7.0.0 起
numkeys必填,参与运算的集合个数,必须与实际提供的 Key 数量一致
key参与求交的集合 Key,数量由 numkeys 指定
LIMIT limit可选,默认 0 表示不限制;大于 0 时达到该数量即停止计算并返回 limit
返回值整数,交集的成员数量
时间复杂度O(N×M) 最坏情况,N 为最小集合成员数,M 为集合个数;带 LIMIT 时可提前终止
ACL@read、@set、@slow
命令标记readonly

官方说明:返回指定集合交集的基数。不存在的 Key 被视为空集合;可选的 LIMIT 参数指定计算的上限,达到上限即返回,默认值 0 表示不限制。$TRAE_REF

numkeys是 Redis 7.0 一批"可变参数"命令(如 ZINTERCARD、LMPOP、ZMPOP)的统一设计:先用一个整数声明后面跟几个 Key,再由服务端校验数量。

二、基础示例

以下命令在测试实例的 redis-cli 中执行。文中结果是预期说明,未实际连接 Redis 运行。示例沿用官方文档的数据与结果。

DEL tutorial:{sintercard}:key1 tutorial:{sintercard}:key2 SADD tutorial:{sintercard}:key1 "a" "b" "c" "d" SADD tutorial:{sintercard}:key2 "a" "c" "d" "e" SINTERCARD 2 tutorial:{sintercard}:key1 tutorial:{sintercard}:key2 SINTERCARD 2 tutorial:{sintercard}:key1 tutorial:{sintercard}:key2 LIMIT 2

预期结果:两条 SADD 各返回4;第一条 SINTERCARD 返回(integer) 3(交集为 a、c、d);第二条带LIMIT 2返回(integer) 2,因为数到第 2 个交集成员就提前终止。

三、LIMIT 的语义

这是 SINTERCARD 相对 SINTER 最核心的价值,也是最容易误解的地方:

  • LIMIT 0(默认):不限制,返回完整交集基数。
  • LIMIT n(n > 0):最多数到 n 就停,返回值为min(真实交集大小, n)。
  • LIMIT为负数:报错,不会当作"不限制"。

因此LIMIT n返回n只能说明"交集至少有 n 个",不能说明恰好有 n 个。业务上常用于"是否存在至少 n 个共同点"的布尔判断:返回 n 即条件成立,返回小于 n 即条件不成立。

SINTERCARD 2 tutorial:{sintercard}:key1 tutorial:{sintercard}:key2 LIMIT 1 SINTERCARD 2 tutorial:{sintercard}:key1 tutorial:{sintercard}:key2 LIMIT 10

预期结果:LIMIT 1返回1(交集至少 1 个,实际是 3 个);LIMIT 10返回3(阈值大于真实交集,返回完整数量)。

四、numkeys 的校验

numkeys必须与实际 Key 数量严格一致,否则报错:

情形结果
numkeys 与实际 Key 数一致正常执行
numkeys 小于实际 Key 数多余的参数会被当作语法错误处理
numkeys 大于实际 Key 数报错,提示 Key 数量不足
numkeys 为 0 或负数报错,必须是正整数
numkeys 不是整数报ERR value is not an integer or out of range
SINTERCARD 2 tutorial:{sintercard}:key1 SINTERCARD 0 tutorial:{sintercard}:key1

预期结果:第一条声明 2 个 Key 却只给了 1 个,报参数数量错误;第二条 numkeys 为 0,报 numkeys 必须大于 0 的错误。

五、不存在的 Key 与空结果

场景返回
所有 Key 都存在且有交集交集成员数量(正整数)
任一 Key 不存在0(不存在的集合视为空集)
所有 Key 都存在但无公共成员0
SINTERCARD 2 tutorial:{sintercard}:key1 tutorial:{sintercard}:nokey

预期结果:返回0。与 SINTER 一致,任一 Key 不存在即交集为空——这与差集 SDIFF 的"后续 Key 不存在不影响结果"形成鲜明对比。

六、边界情况与错误处理

场景行为
缺少 numkeys报语法错误
numkeys 与实际 Key 数不符报参数数量错误
LIMIT 为负数报LIMIT can't be negative
LIMIT 不是整数报ERR value is not an integer or out of range
任一 Key 类型不是 Set报 WRONGTYPE
只传一个 Key(numkeys 1)返回该集合的基数
SET tutorial:{sintercard}:str text SINTERCARD 2 tutorial:{sintercard}:key1 tutorial:{sintercard}:str SINTERCARD 2 tutorial:{sintercard}:key1 tutorial:{sintercard}:key2 LIMIT -1

预期结果:第一条因 str 是 String 类型报 WRONGTYPE;第二条因 LIMIT 为负报LIMIT can't be negative。

七、与相近命令的区别

命令返回是否传输成员LIMIT 支持版本
SINTERCARD交集数量否是7.0.0
SINTER交集成员数组是否1.0.0
SINTERSTORE写入目标后返回数量否(写服务端)否1.0.0
SUNION并集成员是否1.0.0
SDIFF差集成员是否1.0.0
ZINTERCARD有序集合交集数量否是7.0.0

选择规则很清楚:只关心"有多少"或"是否达到阈值"用 SINTERCARD;需要成员内容用 SINTER;需要成员在服务端长期保留用 SINTERSTORE。

SINTERCARD 与 ZINTERCARD 是同一设计的集合版与有序集合版,参数结构一致(numkeys + keys + LIMIT),但 ZINTERCARD 不支持 WEIGHTS/AGGREGATE。

八、客户端示例

前提为 redis-py 版本支持 SINTERCARD(7.0 及以上服务端)。redis-py 提供sintercard(keys, limit=0)。

importredis r=redis.Redis(host="localhost",port=6379,decode_responses=True)k1="tutorial:{sintercard}:py1"k2="tutorial:{sintercard}:py2"try:r.delete(k1,k2)r.sadd(k1,"a","b","c","d")r.sadd(k2,"a","c","d","e")print(r.sintercard([k1,k2]))# 3print(r.sintercard([k1,k2],2))# 2,达到 LIMIT 提前终止print(r.sintercard([k1],0))# 4,单集合即自身基数print(r.sintercard([k1,"no-such"]))# 0finally:r.delete(k1,k2)r.close()

Java(Jedis 5.x)示例,sintercard(keys...)与sintercard(limit, keys...)返回long。Jedis 会自动计算 numkeys,不需要手动传入:

try(Jedisjedis=newJedis("localhost",6379)){Stringk1="tutorial:{sintercard}:java1";Stringk2="tutorial:{sintercard}:java2";jedis.del(k1,k2);jedis.sadd(k1,"a","b","c","d");jedis.sadd(k2,"a","c","d","e");System.out.println(jedis.sintercard(k1,k2));// 3System.out.println(jedis.sintercard(2,k1,k2));// 2,limit=2 提前终止jedis.del(k1,k2);}

注意sintercard(2, k1, k2)中的 2 是limit 而不是 numkeys,这是 Jedis 与原始命令参数顺序上的差异,容易写错。Jedis 较早版本(4.x 及之前)没有该方法,需升级到 5.x 或自行用sendCommand发送原始命令。

九、原子性与并发

只读且原子:SINTERCARD 不修改数据,单命令原子,返回执行瞬间的计数快照。

计数是精确值:结果没有误差,与 SINTER 返回数组的长度一致(未设 LIMIT 时)。这与 PFCOUNT 的近似基数不同。

LIMIT 与并发:带 LIMIT 时返回n只代表"至少 n 个",集合在并发写入下随时可能变化,不要把该结果当作稳定不变的精确值缓存。

事务与 Pipeline:可在 MULTI/EXEC、Lua 脚本和管道中正常使用。

集群限制:Redis Cluster 中所有参与运算的 Key 必须落在同一哈希槽,否则报 CROSSSLOT。

十、性能与使用注意事项

省的是带宽而非计算:SINTERCARD 与 SINTER 的复杂度同为 O(N×M),差别在于不把成员序列化并传回客户端。交集很大时,节省的网络与内存开销非常显著。

LIMIT 才是真正的提速手段:达到阈值即停止遍历,能把"判断是否存在共同点"从全量扫描降为常数级。判断"是否有共同好友"时,LIMIT 1是标准写法。

仍然可能阻塞:不带 LIMIT 的大集合求交依旧带@slow标记。必要时在副本执行,或先做数据分片。

不能替代"读成员":SINTERCARD 只返回数量。后续需要用成员时,仍需 SINTER 或 SINTERSTORE。

十一、典型业务场景

共同好友数量:SINTERCARD 2 user:{a}:friends user:{b}:friends直接得到共同好友数,不必取回全部集合再求长度。若只需判断"有没有共同好友",加LIMIT 1。

多条件筛选取量:商品颜色、尺寸、品牌三个集合求交的基数,用于展示"当前筛选条件下共 N 件商品",避免传输大量 ID。

权限覆盖率判断:用户角色集合与所需角色集合的交集数量是否达到要求,用 LIMIT 做快速判定。

推荐去重计数:候选集合与已曝光集合的交集数量,用于评估推荐重复率。

风控同时命中规则数:多个规则集合的交集大小,作为风险评分输入。