Redis怎样找出新增的关注对象_基于Set的SDIFF指令求取差集

2次阅读

sdiff 不能直接找出“新增关注”,因其仅执行集合差运算且不记录时间顺序;需先构建两个语义明确的快照集合(如按日期命名),再用 sdiff 计算差集,否则易因键名错误、空键或客户端处理问题导致结果异常。

Redis怎样找出新增的关注对象_基于Set的SDIFF指令求取差集

SDIFF 能不能直接找出“新增关注”

不能——SDIFF 本身只做集合差运算,不记录时间或顺序。所谓“新增”,本质是对比两个时间点的 follow_set:旧快照 vs 新快照。你得先有这两个集合,SDIFF 才能算出“新加入的成员”。常见错误是拿当前关注集和一个空集、或和用户资料集去差,结果要么全返回、要么恒为空。

怎么构造两个可比的 Set

关键在命名和写入时机。必须让 redis 里同时存在两个有明确语义的 Set:

  • follow:uid:123:20240520(昨天快照)
  • follow:uid:123:20240521(今天快照)

或者更稳妥地用带过期的临时键:follow:uid:123:tmp_newfollow:uid:123:tmp_old,每次更新前先 RENAME 旧键再写新键。别用 SADD 增量写入后直接差——那不是“新增”,是“当前全量减去某静态参考集”,语义错位。

SDIFF 返回结果为空却以为有新增

典型原因有三个:

  • 两个键名拼错,比如少写了 :uid: 或日期格式不一致(2024-05-21 vs 20240521),SDIFF 对不存在的键视为空集,SDIFF a b 中若 b 不存在,结果等价于 SMEMBERS a
  • 用了 SDIFFSTORE 但目标键已存在且没清空,导致结果被追加而非覆盖
  • 客户端自动去重或截断了返回的 RESP2 数组,尤其在某些 lua 脚本或旧版驱动里,把单元素结果误判为 nil

调试时先手动跑:SDIFF follow:uid:123:20240520 follow:uid:123:20240521,看原始输出是否符合预期。

性能和数据一致性要注意什么

大关注量用户(比如百万级)下,SDIFF 是 O(N+M) 时间复杂度,N、M 分别为两个 Set 的基数。如果每天全量 dump 再 diff,内存和 CPU 压力会随关注数线性上涨。更轻量的做法是改用「增量日志」:每次 SADD 同时往 follow_log:uid:123(List 或 Stream)推一条记录,再用 XREAD 拉取未处理的新增 ID。不过这就脱离 SDIFF 场景了——真正要用 SDIFF,就得接受它只适合中低频、中小规模的离线比对。

另外,Redis Cluster 下 SDIFF 要求所有 key 在同一个 slot,否则报 CROSSSLOT Keys in request don't hash to the same slot 错误。所以键名设计必须带相同哈希标签,比如都写成 {follow:uid:123}:20240520{follow:uid:123}:20240521

text=ZqhQzanResources