当前位置:首页 > 文章列表 > 数据库 > Redis > Redis SCAN 为什么不能当作一次性全量遍历

Redis SCAN 为什么不能当作一次性全量遍历

来源:17golang原创 2026-10-23 05:03:38 0浏览 收藏

Redis 的 SCAN 不能当成“一次请求就拿到全量键”的快照查询。它是游标式增量遍历:从游标 0 开始,把本次返回的游标交给下一次请求,直到返回游标再次变成 0,这才叫完成一次完整遍历。

官方地址:https://redis.io/

要点速览
  • 单次 SCAN 返回的是一批键和下一游标,不承诺是完整列表、固定数量或稳定顺序。
  • 完整遍历能覆盖从开始到结束都持续存在的键,但同一个键可能返回多次,应用必须允许重复处理。
  • MATCH 和 COUNT 都不能把键空间变成快照;键空间持续增长时,完整遍历也可能无法结束。

把 SCAN 看成游标迭代而不是快照

我在清理带前缀的缓存键时最容易踩的坑,是把第一条 SCAN 0 MATCH cache:* 的结果直接当成“所有匹配键”。这只代表游标的一小段位置。Redis 官方定义的完整遍历,是从 0 开始,并持续使用上一轮返回的游标,直到返回 0。

Redis 键空间、SCAN 游标、返回键集合和下一次请求之间的静态关系说明图
图1:SCAN 游标与返回键集合的关系说明图,不是运行截图或全量快照。

最小的命令循环可以这样写:

# 每轮沿用 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 都不能提前结束。一个键也可能因为底层哈希表调整而被返回多次,所以删除、迁移、补偿等动作要设计成幂等,或在应用侧维护去重集合。

Redis SCAN 稳定存在、重复、动态变化、MATCH、COUNT 与幂等处理之间的静态边界说明图
图2:SCAN 完整遍历保证与动态键空间边界说明图,不是监控截图。

MATCH 和 COUNT 只能改变返回方式

MATCH 是 glob 风格的过滤条件,但过滤发生在元素被扫描之后。匹配很少时,连续几轮返回空集合并不异常。不要因为某一轮为空就认为遍历完成,也不要把 MATCH 当成降低整个键空间扫描工作的索引。

COUNT 默认值是 10,作用是提示每轮投入多少工作量。它不是保证返回 100 个键的分页参数,Redis 允许某轮返回更少、更多,甚至返回空集合。生产任务应按延迟和服务器负载调节它,而不是用返回数量判断是否结束。

现象正确判断处理方式
本轮返回空列表游标可能仍未归零继续使用返回游标
同一键出现两次属于允许的重复让处理动作幂等,必要时去重
希望严格按创建时间分页SCAN 不提供排序快照改用有序集合、数据库分页或专门索引

动态键空间里什么时候不适合用 SCAN

SCAN 适合把一次可能阻塞很久的全库操作拆成多次小调用,但它仍然要付出完整遍历的总成本。若业务在遍历期间持续高速写入,键空间可能一直增长,Redis 官方也明确说明这种情况下完整遍历不一定能终止。

因此,定时清理任务可以接受“遍历期间的近似时点”和重复处理;需要严格一致的名单、稳定排序或一次性快照时,就不该只靠 SCAN。可以在写入时维护集合或有序集合,给任务建立明确的边界时间,并把处理结果写入幂等记录,再用 SCAN 做补偿扫描。

常见问题

SCAN 看到游标 0 就一定没有键了吗?

游标回到 0 表示这一轮遍历结束,不表示数据库为空,也不表示遍历期间变化过的键都被纳入了同一快照。

COUNT 100 能保证每次返回 100 个键吗?

不能。COUNT 是实现层面的工作量提示,返回数量可能少于、接近或不同于这个值,空返回也可能出现。

如何避免重复处理?

优先把删除、刷新或迁移动作设计成幂等;如果任务必须在单轮内去重,再用集合记录已经处理的键,但要评估额外内存和任务时长。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Redis Lua 脚本怎样通过 KEYS 和 ARGV 区分参数Redis Lua 脚本怎样通过 KEYS 和 ARGV 区分参数
上一篇
Redis Lua 脚本怎样通过 KEYS 和 ARGV 区分参数
VS Code 怎样只搜索当前工作区文件夹
下一篇
VS Code 怎样只搜索当前工作区文件夹
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    603次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    643次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    673次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    639次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    460次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码