SMEMBERS 的替代思路
SMEMBERS 一次性返回集合全部成员,集合越大代价越高:主线程要构造完整回复,输出缓冲按成员总量膨胀。大集合的正确读法是渐进遍历(SSCAN)或按业务桶拆分;只关心数量时用 SCARD,只关心交集数量时用 SINTERCARD,都比先取全量再计算划算。
基本信息
| 渐进遍历 | SSCAN key cursor [MATCH 模式] [COUNT n] |
|---|---|
| 全量返回 | SMEMBERS(大集合上避免使用) |
| 只要数量 | SCARD,复杂度 O(1) |
| 交集计数 | SINTERCARD numkeys key… [LIMIT n](Redis 7.0 起) |
| 随机抽样 | SRANDMEMBER 不删除,SPOP 会删除成员 |
| 规模观测 | SCARD 配合 MEMORY USAGE |
典型使用场景
- 标签与关系类集合读取:用 SSCAN 渐进遍历,避免一次性全量
- 集合运算前先控规模:交集并集随规模放大,先按桶拆分再计算
- 只求数量:用 SCARD 或 SINTERCARD,避免取全量再计数
- 随机抽样校验:SRANDMEMBER 抽几个成员对账,不影响集合内容
- 边遍历边处理:遍历期间可以增删,但要按弱一致语义去重
最小示例
最小示例
redis-cli SCARD big:set # 先看规模
redis-cli SSCAN big:set 0 COUNT 100 # 渐进遍历一批
redis-cli SSCAN big:set 0 MATCH tag:* COUNT 100 # 带模式匹配的遍历
redis-cli SINTERCARD 2 set:a set:b LIMIT 100 # 只算交集数量(7.0 起)
redis-cli SRANDMEMBER big:set 10 # 随机抽 10 个,不删除
redis-cli MEMORY USAGE big:set # 大 key 体积评估替代方案对照
| 需求 | 命令 | 注意 |
|---|---|---|
| 全量遍历 | SSCAN 分页 | COUNT 只是提示,单次可能返回更多元素 |
| 只要总数 | SCARD | O(1),比取全量再计数划算得多 |
| 交集与并集结果 | SINTER、SUNION、SDIFF | 复杂度随规模放大,大集合慎用 |
| 交集数量 | SINTERCARD | 7.0 起支持,可用 LIMIT 提前收敛 |
| 随机抽取 | SRANDMEMBER | 不改变集合;需要剔除成员则用 SPOP |
SSCAN 在遍历期间发生增删时可能返回重复元素,但保证返回遍历全程都存在的元素;调用方要按弱一致语义做去重处理。
带 STORE 的运算会覆盖目标键:SINTERSTORE 若把结果写进正在使用的键,会静默覆盖业务数据,执行前务必核对键名。
对超大集合直接全量返回或做集合运算,会长时间占用主线程并放大输出缓冲;先迁移到分片结构,再考虑计算。