Redis命令:SINTERSTORE
Redis SINTERSTORE 命令详细教程SINTERSTORE计算多个集合的交集并把结果写入指定的目标 Key返回写入的成员数量。它是SINTER的写版本SINTER 把交集返回给客户端SINTERSTORE 把交集留在 Redis 里便于缓存、后续运算或分页读取。命令从 Redis 1.0.0 起提供目标 Key 会被完全覆盖结果为空时目标 Key 会被删除。资料合集https://pan.quark.cn/s/10e98d308913、https://pan.quark.cn/s/f56bc69c5338一、概览与语法SINTERSTORE destination key [key ...]项目说明数据类型Set支持版本Redis 1.0.0 起destination结果写入的目标 Key已存在时被覆盖key至少一个参与运算的集合全部参与求交返回值整数写入目标集合的成员数量结果为空时返回 0时间复杂度O(N×M) 最坏情况N 为最小集合成员数M 为集合个数ACLwrite、set、slow命令标记write、denyoom官方说明计算所有指定集合的交集并把结果存储在 destination 中。若 destination 已存在则被覆盖。$TRAE_REF二、基础示例以下命令在测试实例的 redis-cli 中执行。文中结果是预期说明未实际连接 Redis 运行。示例沿用官方文档的数据与结果。DEL tutorial:{sinterstore}:key1 tutorial:{sinterstore}:key2 tutorial:{sinterstore}:key SADD tutorial:{sinterstore}:key1 a b c SADD tutorial:{sinterstore}:key2 c d e SINTERSTORE tutorial:{sinterstore}:key tutorial:{sinterstore}:key1 tutorial:{sinterstore}:key2 SCARD tutorial:{sinterstore}:key SMEMBERS tutorial:{sinterstore}:key预期结果两条 SADD 各返回3SINTERSTORE 返回1SCARD 返回1SMEMBERS 返回c。只有c同时存在于两个源集合。三、destination 的覆盖与删除这是本命令最容易出问题的行为destination 原状态运算后不存在创建并写入结果已存在结果非空旧内容被整体覆盖旧成员全部丢失已存在结果为空destination 被删除Key 不再存在是其他数据类型被覆盖为 SetDEL tutorial:{sinterstore}:overwrite tutorial:{sinterstore}:s1 tutorial:{sinterstore}:s2 SADD tutorial:{sinterstore}:overwrite old1 old2 SADD tutorial:{sinterstore}:s1 x y SADD tutorial:{sinterstore}:s2 y z SINTERSTORE tutorial:{sinterstore}:overwrite tutorial:{sinterstore}:s1 tutorial:{sinterstore}:s2 SMEMBERS tutorial:{sinterstore}:overwrite SCARD tutorial:{sinterstore}:overwrite预期结果SINTERSTORE 返回1SMEMBERS 只返回y旧的old1、old2已被清除SCARD 返回1。覆盖是replace而不是merge。如果 destination 之前存有业务数据一次误调用就会永久丢失务必使用独立的结果 Key。四、空结果的删除语义当交集为空时destination 不是变成空集合而是 Key 整体消失DEL tutorial:{sinterstore}:empty SADD tutorial:{sinterstore}:a1 x SADD tutorial:{sinterstore}:a2 y SINTERSTORE tutorial:{sinterstore}:empty tutorial:{sinterstore}:a1 tutorial:{sinterstore}:a2 EXISTS tutorial:{sinterstore}:empty SCARD tutorial:{sinterstore}:empty预期结果SINTERSTORE 返回0EXISTS 返回0SCARD 返回0。三者一致说明 Key 已被删除。这一行为对缓存场景很关键缓存 Key 消失后读取方看到的是不存在需要用 SCARD 或 EXISTS 判断而不能假设返回空数组即缓存命中但结果为空。五、destination 参与运算destination 可以与源 Key 同名Redis 会先完整计算再写入不会出现边算边改的问题DEL tutorial:{sinterstore}:self SADD tutorial:{sinterstore}:self a b SINTERSTORE tutorial:{sinterstore}:self tutorial:{sinterstore}:self SMEMBERS tutorial:{sinterstore}:self预期结果SINTERSTORE 返回2SMEMBERS 返回a、b。只传一个 Key 时交集就是它自己。虽然语义正确但这种写法可读性差容易让维护者误以为发生了自引用错误。建议把结果写到带:result后缀的独立 Key。六、边界情况与错误处理场景行为只传 destination 不传 key报语法错误只传一个 key返回该集合全部成员等价于复制任一 Key 不存在交集为空destination 被删除返回 0任一 Key 类型不是 Set报 WRONGTYPEdestination 不被修改destination 是其他类型被覆盖为 Set不报错SET tutorial:{sinterstore}:str text SINTERSTORE tutorial:{sinterstore}:dst tutorial:{sinterstore}:key1 tutorial:{sinterstore}:str SINTERSTORE tutorial:{sinterstore}:dst2预期结果第一条因参与运算的 str 是 String 类型报 WRONGTYPEdst 不会被创建第二条缺少参与运算的 key报ERR wrong number of arguments for sinterstore command。七、与相近命令的区别命令结果去向是否覆盖目标是否传输成员返回SINTERSTORE写入 destination是否写入数量SINTER只返回客户端无是成员数组SINTERCARD只返回数量无否整数SDIFFSTORE差集写入 destination是否写入数量SUNIONSTORE并集写入 destination是否写入数量SMEMBERS读取单个集合无是成员数组三兄弟的选择需要成员且本次就用SINTER只需要数量SINTERCARD结果要落地复用SINTERSTORE。八、客户端示例前提为已安装 redis-py 并准备好本地测试实例。redis-py 的sinterstore(dest, keys, *args)返回写入数量。importredis rredis.Redis(hostlocalhost,port6379,decode_responsesTrue)k1tutorial:{sinterstore}:py1k2tutorial:{sinterstore}:py2desttutorial:{sinterstore}:pydesttry:r.delete(k1,k2,dest)r.sadd(k1,a,b,c)r.sadd(k2,c,d,e)print(r.sinterstore(dest,[k1,k2]))# 1print(r.smembers(dest))# {c}r.srem(k2,c)print(r.sinterstore(dest,[k1,k2]))# 0交集为空print(r.exists(dest))# 0目标被删除finally:r.delete(k1,k2,dest)r.close()JavaJedis示例sinterStore(dest, keys...)返回longtry(JedisjedisnewJedis(localhost,6379)){Stringk1tutorial:{sinterstore}:java1;Stringk2tutorial:{sinterstore}:java2;Stringdesttutorial:{sinterstore}:javadest;jedis.del(k1,k2,dest);jedis.sadd(k1,a,b,c);jedis.sadd(k2,c,d,e);System.out.println(jedis.sinterStore(dest,k1,k2));// 1System.out.println(jedis.smembers(dest));// [c]jedis.del(k1,k2,dest);}九、原子性与并发单命令原子计算与写入在同一条命令中完成其他客户端看不到算完但未写的中间状态。并发覆盖多个生产者向同一 destination 执行 SINTERSTORE 时最终内容取决于执行顺序后执行者完全覆盖先执行者。不要把同一个 destination 当作共享累加器。结果非快照命令结束后 destination 仍是普通集合可被后续 SADD/SREM 修改也可被 EXPIRE 设置过期。若希望结果生成即固定需在写入后立即设置 TTL 或限制写入权限。集群限制Redis Cluster 中 destination 与所有参与运算的 Key 必须落在同一哈希槽否则报 CROSSSLOT。多个 Key 加相同哈希标签即可保证同槽。十、性能与使用注意事项复杂度 O(N×M)N 是最小集合的成员数M 是集合个数。Redis 会选择最小集合为起点遍历再对每个成员做存在性检查。比 SINTER 多一次写入成本结果需要实际存储占用内存。若只是临时用一次用 SINTER 更合适。避免取回再写回客户端先 SINTER 再 SADD 需要两次往返且两次之间数据可能变化SINTERSTORE 在服务端一次原子完成既省往返也避免竞态。预计算缓存的典型用法数据变更时触发 SINTERSTORE 写入缓存集合并紧接EXPIRE读取方直接用 SCARD/SMEMBERS避免每次请求都做交集运算。大集合仍会阻塞带slow标记必要时在副本执行或离线批处理。十一、典型业务场景共同好友缓存把两个用户关注集合的交集写入common:{a}:{b}并设短 TTL前端翻页读缓存避免重复求交。多标签筛选中台把颜色 ∩ 尺寸 ∩ 品牌的交集写入筛选结果集合供商品列表分页读取。分页场景下这个模式比 SINTER 客户端分页更稳因为结果集合已固定。权限交集校验用户角色集合与接口要求集合求交后落库到临时 Key供审计查询。同时在线用户快照多个业务线在线集合求交后写入快照 Key供大屏展示。推荐候选交集把候选集与可用集求交后写入eligible:{scene}线上服务直接消费。