You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取Redis中所有Key命名空间?SCAN命令匹配问题求助

解决Redis提取键命名空间的问题

你遇到的问题很典型——Redis的SCAN命令里的MATCH选项只支持glob风格的通配符(比如*匹配任意字符、?匹配单个字符),完全不支持PCRE正则表达式,所以你用(^\w+):这种正则语法自然匹配不到任何结果。下面给你几个实用的解决思路:

方案一:客户端端处理(简单易上手)

先用SCAN(或redis-cli --scan)获取所有键,然后在本地客户端对键进行分割提取,最后去重。比如用shell命令一行搞定:

redis-cli --scan | awk -F ':' '{print $1}' | sort -u
  • redis-cli --scan:替代KEYS *,避免阻塞Redis服务(尤其是大实例)
  • awk -F ':' '{print $1}':按冒号分割每个键,提取第一部分(命名空间)
  • sort -u:对结果去重,得到唯一的命名空间列表

如果用Python、Java等编程语言的Redis客户端,逻辑类似:遍历扫描到的每个键,用字符串分割函数取冒号前的部分,存入集合自动去重即可。

方案二:服务端Lua脚本处理(高效少传输)

如果你的键数量极大,把所有键传输到客户端再处理会浪费带宽,这时可以用Redis的Lua脚本在服务端直接完成提取和去重:

-- 定义存储命名空间的字典(自动去重)
local namespaces = {}
local cursor = "0"

repeat
    -- 扫描一批键
    local scan_result = redis.call("SCAN", cursor, "COUNT", 1000)
    cursor = scan_result[1]
    local keys = scan_result[2]

    -- 遍历每个键,提取命名空间
    for _, key in ipairs(keys) do
        -- 用Lua的正则匹配冒号前的部分
        local ns = string.match(key, "^(%w+):")
        if ns then
            namespaces[ns] = true
        end
    end
until cursor == "0"

-- 把字典转成列表返回
local result = {}
for ns in pairs(namespaces) do
    table.insert(result, ns)
end
return result

把脚本保存成extract_namespaces.lua,然后用redis-cli执行:

redis-cli EVAL "$(cat extract_namespaces.lua)" 0

这个方案的好处是所有处理都在Redis服务端完成,只返回最终的命名空间列表,大幅减少网络数据传输。注意调整COUNT参数(比如1000),值越大扫描速度越快,根据你的实例规模调整即可。

方案三:Glob前缀匹配(适合已知候选前缀的场景)

如果你的命名空间是预先已知的几个候选值,也可以用SCAN的MATCH逐个匹配前缀,比如:

127.0.0.1:6379> SCAN 0 MATCH "foo:*" COUNT 10
127.0.0.1:6379> SCAN 0 MATCH "bar:*" COUNT 10

但这个方案的局限性很明显——如果命名空间未知或数量太多,就无法覆盖所有情况,所以只适合特定场景。

补充说明

Redis之所以不让SCAN的MATCH支持正则,是因为正则匹配的性能开销远大于glob通配符,而SCAN的设计目标是低开销的增量扫描,所以官方只保留了简单的glob过滤能力。

内容的提问来源于stack exchange,提问作者Paul Serikov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:56:52