1. 线上一个 KEYS 把 Redis 拖垮的真实场景先说结论在 Redis 里按前缀批量查 key能用SCAN就别用KEYS。KEYS pattern这个命令看起来最直观KEYS user:*一把梭但它有两个致命问题一是时间复杂度是 O(N)N 是整个库的 key 总数不是匹配到的数量二是 Redis 处理命令是单线程的KEYS执行期间会阻塞其他所有请求key 越多卡得越久。我遇到过最典型的一次是某个业务方在监控面板上想统计一下order:cache:*到底有多少条直接在客户端敲了KEYS order:cache:*。当时那个实例大概 800 万 key命令发出去之后整个实例的 P99 从 2ms 飙到 3 秒多上游接口大面积超时最后是靠重启才缓过来。从那以后我们内部直接把KEYS加进了命令黑名单用rename-command禁掉。那按前缀查 key 这个需求本身是合理的比如清理某类缓存、做数据迁移、排查脏数据都需要按前缀捞一批 key。正确的做法是用SCAN的游标遍历它每次只返回一小批不阻塞主线程客户端拿着游标一轮轮翻直到游标回到 0 表示遍历结束。代价是它不保证强一致快照遍历过程中数据被改动可能漏掉或重复但对绝大多数「按前缀找 key」的场景完全够用。这篇就围绕SCAN讲清楚三件事命令参数怎么配、MATCH前缀骨架怎么写、COUNT怎么调最后给你一套用redis-cli验证遍历完整性和阻塞耗时的具体动作。如果你在写代码时需要调用模型能力来辅助生成或审查这类脚本可以顺手用 TaoToken 的模型对话做对照地址是 https://taotoken.net/api 模型对话入口在 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmodel-chat 。2. SCAN 命令骨架与 COUNT、MATCH 参数拆解SCAN的完整语法是SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]四个部分逐个说。cursor是游标第一次调用传0之后每次传上一次返回的游标值。当返回的游标又是0时说明这一轮遍历结束。注意游标不是「第几个 key」这种偏移量它是一个内部哈希表的反向二进制迭代游标所以你会看到它跳来跳去比如 0 → 17 → 288 → 224这是正常的别试图去理解它的数值规律。MATCH pattern是模式匹配支持 glob 风格通配符*匹配任意字符?匹配单个字符[abc]匹配字符集。按前缀查就是MATCH user:*这种写法。这里有个关键点必须记住MATCH 是在元素被扫描出来之后才做过滤的不是先按 pattern 去定位数据。也就是说COUNT 10表示「这次从哈希表里扫 10 个槽位」扫出来的这 10 个里可能一个都不匹配user:*于是你看到返回空列表但游标还在往前走。这就是为什么小 COUNT 配窄前缀时会连续好几次返回空结果。COUNT count是每次扫描的工作量提示默认 10。官方文档明确说它只是个 hint实际返回条数可能比 COUNT 多也可能少取决于内部编码比如 ziplist、intset、hashtable 的槽位分布。所以别把 COUNT 当成「精确返回 N 条」。TYPE type是 Redis 6.0 之后加的可以只扫指定类型的 key比如TYPE string能进一步减少无效匹配前缀 类型双过滤时很有用。一个最小可用的前缀遍历骨架长这样# 第一轮游标从 0 开始 SCAN 0 MATCH user:* COUNT 1000 # 假设返回游标 512 SCAN 512 MATCH user:* COUNT 1000 # 继续直到返回的游标为 0用 shell 写一个自动翻页的循环方便在redis-cli里直接跑#!/bin/bash # scan_prefix.sh 用法: ./scan_prefix.sh user:* 1000 PATTERN${1:-*} COUNT${2:-1000} CURSOR0 TOTAL0 while :; do # 用 --raw 去掉引号方便解析 RESULT$(redis-cli --raw SCAN $CURSOR MATCH $PATTERN COUNT $COUNT) CURSOR$(echo $RESULT | head -n 1) KEYS$(echo $RESULT | tail -n 2) if [ -n $KEYS ]; then echo $KEYS N$(echo $KEYS | wc -l) TOTAL$((TOTAL N)) fi if [ $CURSOR 0 ]; then break fi done echo ---- total matched: $TOTAL ---- 2这段脚本的核心就是「拿游标 → 取结果 → 判断游标是否为 0」。--raw参数很关键不加的话redis-cli会给每个元素加引号解析起来很烦。3. COUNT 调优为什么 1000 是个常用起点COUNT 的取值直接决定两件事网络往返次数和单次阻塞时长。COUNT 太小比如默认的 10800 万 key 的库你要来回 80 万次网络 RTT 累加起来非常可观而且每次返回空结果的概率高客户端循环空转。COUNT 太大比如直接上 10 万单次SCAN内部要扫的槽位多虽然不像KEYS那样一次性全扫但单次耗时也会拉长阻塞风险上升。我的经验值是这样场景建议 COUNT理由前缀命中率高如user:*占大半500 ~ 1000每次都能返回不少结果往返次数少前缀命中率低如tmp:lock:*很稀疏2000 ~ 5000抵消 MATCH 后置过滤带来的空返回结果集预期 1 万以内直接设为预期大小一轮基本扫完最省事超大库 在线业务500 起步观察耗时再调优先保证不阻塞有个常见误区以为 COUNT 是「返回结果条数」。不是的COUNT 是「扫描的槽位数量」MATCH 过滤后返回的才是结果。所以前缀越稀疏COUNT 越要往大调否则你会看到连续十几次空返回。另外 COUNT 每次调用可以不一样只要游标接得上就行。比如第一轮用 1000 探路发现返回结果很少后面几轮直接提到 5000完全合法。4. 用 redis-cli 验证遍历完整性与阻塞耗时光会写命令不够得能验证「遍历全不全」和「到底阻不阻塞」。下面这套动作可以直接照做。4.1 造测试数据先灌一批带前缀的 key方便验证# 灌 10000 个 user: 前缀的 key for i in $(seq 1 10000); do redis-cli SET user:$i v$i /dev/null done # 再灌 5000 个 order: 前缀的 key 做干扰 for i in $(seq 1 5000); do redis-cli SET order:$i v$i /dev/null done4.2 验证遍历完整性用DBSIZE拿到总数再用SCAN遍历user:*对比数量redis-cli DBSIZE # 预期 15000 # 用第 2 节的脚本遍历 ./scan_prefix.sh user:* 1000 | wc -l # 预期 10000脚本最后一行 total 输出到了 stderr不影响 wc如果数量对得上说明遍历完整。如果对不上先检查是不是遍历过程中有写入SCAN不保证快照一致边写边扫可能漏。4.3 验证阻塞耗时这是最关键的一步对比KEYS和SCAN的耗时。用redis-cli --latency开一个窗口持续观察延迟另一个窗口执行命令# 窗口 A持续观察延迟 redis-cli --latency # 窗口 B执行 KEYS观察窗口 A 的延迟尖刺 redis-cli KEYS user:* /dev/null # 窗口 B执行 SCAN 单轮观察窗口 A 是否平稳 redis-cli SCAN 0 MATCH user:* COUNT 1000 /dev/null实测下来KEYS那一瞬间窗口 A 的延迟会明显跳高而SCAN单轮基本看不到尖刺。你也可以用redis-cli --intrinsic-latency 100看基线再在执行命令时对比。更严谨一点用INFO commandstats看命令耗时统计redis-cli INFO commandstats | grep -E cmdstat_keys|cmdstat_scancmdstat_keys的usec_per_call会明显高于cmdstat_scan而且keys的calls通常很少因为被禁了scan的调用次数多但单次耗时低。5. 本篇常见错排查报错一ERR unknown command SCAN或NOPERM this user has no permissions to run the scan command前者说明 Redis 版本太老2.8 以下升级即可。后者是 ACL 权限问题Redis 6 之后默认用户可能没给scan权限需要管理员授权redis-cli ACL SETUSER myuser scan dbsize报错二遍历结果比预期少最常见原因是遍历期间有 key 被删除或新增。SCAN是弱一致遍历不保证快照。如果业务要求精确要么在低峰期做要么用DUMPRESTORE做快照副本再扫。另一个原因是MATCH写错了比如user*漏了冒号会匹配到username这类无关 key。报错三连续多次返回空列表以为命令坏了这是MATCH后置过滤的正常现象不是 bug。把COUNT调大或者接受空返回继续翻游标。判断是否结束只看游标是否为 0不要看结果是否为空。报错四客户端循环里游标类型搞错SCAN返回的游标是字符串有些客户端库返回的是数字比较时要注意类型。比如 Jedis 里ScanParams.SCAN_POINTER_START是字符串0别拿int 0去比。Python 的redis-py里scan_iter已经帮你封装好了游标循环直接用更省心import redis r redis.Redis(host127.0.0.1, port6379, decode_responsesTrue) for key in r.scan_iter(matchuser:*, count1000): print(key)报错五SCAN和HSCAN、SSCAN、ZSCAN搞混SCAN扫的是整个 key 空间HSCAN扫的是某个 hash 的 fieldSSCAN扫 set 成员ZSCAN扫 zset 成员。按前缀查 key 用SCAN别用错。6. 落地建议与工具链衔接把SCAN用稳记住三条前缀查 key 一律走SCANKEYS在生产环境直接禁COUNT按前缀稀疏度调稀疏就往大调遍历结束只看游标是否为 0别被空返回吓到。如果你在写这类运维脚本或封装工具类时需要快速验证一段逻辑、生成对照代码可以用 TaoToken 的模型对话能力做辅助入口在 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmodel-chat 。长期做编码和 Agent 类项目的话Coding Plan 更适合持续调用地址是 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentcoding-plan 。需要管理调用凭证就去 API Keys 页面 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentapi-keys 接入细节看文档 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentdoc 。最后补一个实战小技巧如果你的前缀查询是高频操作与其每次SCAN全库不如在写入时维护一个前缀索引 set比如SET user:1的同时SADD idx:user user:1查的时候直接SMEMBERS idx:user。代价是写入多一步、要处理过期同步但查询从 O(N) 降到 O(1)。这个方案适合前缀种类固定、查询频繁的场景SCAN则适合临时排查和低频迁移。两者不冲突按场景选。
企业数字化 ERP 产品动态
相关推荐
飞书 CodeM 上手实测:从写代码到修 Bug,AI 研发同事到底有多好用 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 19:24:47
竞价sem培训避坑指南:3个实战案例拆解建站成本 竞价sem培训避坑指南:3个实战案例拆解建站成本 找建站公司最怕被坑高价,很多老板一听到“定制开发”就捂紧钱包,生怕被宰一刀。其实, 竞价sem培训… · 2026/9/27 19:56:39
2026京东笔试真题【风控排序评估】多语言题解 风控排序评估(C++/Py/Java /Js/Go)题解 京东 2026年9月19号 笔试真题 第一题 题目内容
风控侧要对一批交易做欺诈打分。每笔交易有真实标签 tit_iti · 2026/9/27 19:56:33
知识库自动化实战:微信文章自动同步与 AI 编译系统配置指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 19:56:33
2026京东笔试真题【四因子乘积对】多语言题解 四因子乘积对(C++/Py/Java /Js/Go)题解 京东 2026年8月29号 笔试真题 第二题 题目内容
边缘集群里排着 mmm 个推理批次,第 ttt 个批次带着指纹 btb_t · 2026/9/27 19:56:33
招生平台网站开发避坑指南:从0到1的速查手册 招生平台网站开发避坑指南:从0到1的速查手册 网站做好了没人访问?这是做招生平台最头疼的事。很多人花大价钱建站,结果上线后流量惨淡,原因很简单:功能太复杂,搜索权重低。这份速查手册帮你避开90%的坑,让招生平台既有流量又有转化。… · 2026/9/27 19:56:33
湖北微网站建设费用揭秘:避坑最佳实践指南 湖北微网站建设费用揭秘:避坑最佳实践指南 网站做好了没人访问,这才是最让人崩溃的噩梦。很多老板以为付了钱、看到页面就行,结果上线三个月,后台数据一片惨绿。在湖北做微网站,别只看报价单上的数字,更要看这钱花得值不值,有没有包含流量获取的… · 2026/9/27 19:56:21
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现 简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01
汕头网站建设制作厂家避坑指南:5大注意事项救急 汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习 简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现 简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01
汕头网站建设制作厂家避坑指南:5大注意事项救急 汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习 简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01