Redis SCAN 为什么不能当作一次性全量遍历
Redis 的 SCAN 不能当成“一次请求就拿到全量键”的快照查询。它是游标式增量遍历:从游标 0 开始,把本次返回的游标交给下一次请求,直到返回游标再次变成 0,这才叫完成一次完整遍历。
官方地址:https://redis.io/
- 单次
SCAN返回的是一批键和下一游标,不承诺是完整列表、固定数量或稳定顺序。 - 完整遍历能覆盖从开始到结束都持续存在的键,但同一个键可能返回多次,应用必须允许重复处理。
MATCH和COUNT都不能把键空间变成快照;键空间持续增长时,完整遍历也可能无法结束。
把 SCAN 看成游标迭代而不是快照
我在清理带前缀的缓存键时最容易踩的坑,是把第一条 SCAN 0 MATCH cache:* 的结果直接当成“所有匹配键”。这只代表游标的一小段位置。Redis 官方定义的完整遍历,是从 0 开始,并持续使用上一轮返回的游标,直到返回 0。

最小的命令循环可以这样写:
# 每轮沿用 Redis 返回的新游标,返回 0 才结束完整遍历
cursor=0
while :; do
# COUNT 是工作量提示,不是严格的分页大小
reply=$(redis-cli --raw SCAN "$cursor" MATCH 'cache:*' COUNT 100)
# 实际项目中应使用客户端的结构化返回值解析游标和键列表
next_cursor=$(printf '%s\n' "$reply" | sed -n '1p')
printf '%s\n' "$reply" | sed '1d'
[ "$next_cursor" = "0" ] && break
cursor="$next_cursor"
done
示例用 shell 展示游标关系;正式代码应优先使用 Redis 客户端的数组返回值,避免靠换行拆解键名。重点不是一次拿多少,而是不能丢掉下一游标。
完整遍历能保证什么,又不保证什么
如果一个键从遍历开始到结束始终存在,完整遍历保证它至少会在某次返回中出现;如果一个键在开始前已经删除且整个遍历期间没有重新出现,也不会被返回。但这不是快照语义:遍历期间新增或删除的键,是否出现没有同样的确定性。
另外,SCAN 的返回顺序没有业务意义,单次调用可以返回空集合,直到游标回到 0 都不能提前结束。一个键也可能因为底层哈希表调整而被返回多次,所以删除、迁移、补偿等动作要设计成幂等,或在应用侧维护去重集合。

MATCH 和 COUNT 只能改变返回方式
MATCH 是 glob 风格的过滤条件,但过滤发生在元素被扫描之后。匹配很少时,连续几轮返回空集合并不异常。不要因为某一轮为空就认为遍历完成,也不要把 MATCH 当成降低整个键空间扫描工作的索引。
COUNT 默认值是 10,作用是提示每轮投入多少工作量。它不是保证返回 100 个键的分页参数,Redis 允许某轮返回更少、更多,甚至返回空集合。生产任务应按延迟和服务器负载调节它,而不是用返回数量判断是否结束。
| 现象 | 正确判断 | 处理方式 |
|---|---|---|
| 本轮返回空列表 | 游标可能仍未归零 | 继续使用返回游标 |
| 同一键出现两次 | 属于允许的重复 | 让处理动作幂等,必要时去重 |
| 希望严格按创建时间分页 | SCAN 不提供排序快照 | 改用有序集合、数据库分页或专门索引 |
动态键空间里什么时候不适合用 SCAN
SCAN 适合把一次可能阻塞很久的全库操作拆成多次小调用,但它仍然要付出完整遍历的总成本。若业务在遍历期间持续高速写入,键空间可能一直增长,Redis 官方也明确说明这种情况下完整遍历不一定能终止。
因此,定时清理任务可以接受“遍历期间的近似时点”和重复处理;需要严格一致的名单、稳定排序或一次性快照时,就不该只靠 SCAN。可以在写入时维护集合或有序集合,给任务建立明确的边界时间,并把处理结果写入幂等记录,再用 SCAN 做补偿扫描。
常见问题
SCAN 看到游标 0 就一定没有键了吗?
游标回到 0 表示这一轮遍历结束,不表示数据库为空,也不表示遍历期间变化过的键都被纳入了同一快照。
COUNT 100 能保证每次返回 100 个键吗?
不能。COUNT 是实现层面的工作量提示,返回数量可能少于、接近或不同于这个值,空返回也可能出现。
如何避免重复处理?
优先把删除、刷新或迁移动作设计成幂等;如果任务必须在单轮内去重,再用集合记录已经处理的键,但要评估额外内存和任务时长。
Redis Lua 脚本怎样通过 KEYS 和 ARGV 区分参数
- 上一篇
- Redis Lua 脚本怎样通过 KEYS 和 ARGV 区分参数
- 下一篇
- VS Code 怎样只搜索当前工作区文件夹
-
- 数据库 · Redis | 1小时前 |
- Redis Lua 脚本怎样通过 KEYS 和 ARGV 区分参数
- 313浏览 收藏
-
- 数据库 · Redis | 1小时前 |
- Redis ZSET 怎样查询分数区间内的成员
- 484浏览 收藏
-
- 数据库 · Redis | 1小时前 |
- Redis Hash 怎样一次读取多个字段并设置 TTL
- 104浏览 收藏
-
- 数据库 · Redis | 1小时前 |
- Redis Stream 消费组为什么重复收到消息
- 463浏览 收藏
-
- 数据库 · Redis | 1小时前 |
- Redis Stream XREAD COUNT 怎样限制单次读取消息数
- 166浏览 收藏
-
- 数据库 · Redis | 1小时前 |
- Redis Stream 怎样查看消费者组待处理消息
- 250浏览 收藏
-
- 数据库 · Redis | 1小时前 |
- Redis JSON.SET 路径不存在为什么没有创建对象
- 204浏览 收藏
-
- 数据库 · Redis | 1小时前 |
- Redis EXPIRE 怎样只在新 TTL 更短时更新
- 244浏览 收藏
-
- 数据库 · Redis | 1小时前 |
- Redis JSON.SET 怎样只在键存在时更新
- 173浏览 收藏
-
- 数据库 · Redis | 1小时前 |
- Redis CLIENT PAUSE WRITE 的主节点切换步骤与写入保护边界
- 458浏览 收藏
-
- 数据库 · Redis | 1小时前 |
- Redis GETDEL 怎样读取后删除键
- 306浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 603次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 643次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 673次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 639次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 460次使用
-
- Go与Redis实现分布式互斥锁和红锁
- 2022-12-22 117浏览
-
- Go+Redis实现延迟队列实操
- 2023-02-23 426浏览
-
- 一文搞懂Go语言操作Redis的方法
- 2023-01-07 171浏览
-
- Golang分布式应用之Redis示例详解
- 2023-01-07 113浏览
-
- Go Redis客户端使用的两种对比
- 2022-12-30 195浏览

