Redis从2.8版本开始提供COMMAND系列命令,用于查询服务端支持的命令元信息。其中COMMAND GETKEYS的功能很有意思:你给它一条完整的Redis命令,它会告诉你这条命令将会操作哪些Key。这在开发代理、审计工具或者需要按Key做分片路由的场景中特别有用,省去了自己维护一份命令与Key位置的映射表。本文围绕这条命令展开,介绍它的用法、原理和实际应用。

COMMAND GETKEYS的基本语法与返回结构
这条命令的语法非常直接,完整命令作为参数传入即可:
COMMAND GETKEYS SET user:1001 tom 3600 EX 60 COMMAND GETKEYS MSET name jack age 25 COMMAND GETKEYS DEL session:a session:b session:c
第一条命令会返回user:1001,第二条返回name和age两个Key,第三条返回三个session Key。返回值是一个数组,包含了输入命令中所有会被操作到的Key,顺序与它们在原命令中出现的顺序一致。
需要注意参数要求:传入的第一个参数必须是命令本身,后续参数要构成一条完整合法的命令。如果命令本身不合法,比如参数数量不够,服务端会报错。另外,传入的命令必须是完整的原始参数形式,不能省略任何一个参数,因为Key的位置可能依赖参数个数(比如XADD这类可变参数命令)。
还有一个细节值得说明:COMMAND GETKEYS对命令的合法性校验比较宽松,它不会真正执行这条命令,只做静态分析。也就是说即使某个Key当前不存在,或者值类型与命令不匹配,都不影响结果返回,这一点让它可以安全地用于线上流量分析。
哪些命令支持GETKEYS,不支持时怎么办
COMMAND GETKEYS并非对所有命令都有效。对于SET、GET、DEL、EXISTS这类Key位置固定的命令,支持自然没问题。但对于Object命令、SCRIPT系列、EVAL这类本身不直接操作Key的命令,传入后会返回错误,提示无法提取Key。
遇到这种情况,可以通过COMMAND INFO查看命令的元信息来手动推算。COMMAND INFO返回的字段中有三个与Key定位直接相关:firstkey、lastkey和step。以MSET为例,它的firstkey为1,lastkey为-1,step为2,含义是:Key从第1个参数开始出现,倒数第一个位置截止,每隔2个参数取一个作为Key。理解了这三个字段,就能自己写代码解析任意命令的Key列表。
COMMAND INFO mset get eval
1) 1) "mset"
2) (integer) -3
3) 1) write
4) (integer) 0
5) (integer) 0
6) (integer) 0
7) 1) @write
2) @string
3) totemplate
8) (empty array)
9) 1) 1) "keystart"
2) (integer) 1
2) 1) "keyend"
2) (integer) -1
3) 1) "keystep"
2) (integer) 2从Redis 7.0开始,还提供了COMMAND GETKEYSANDFLAGS命令,除了返回Key列表外,还返回每个Key的访问标志(读、写、插入等),对区分读写命令、实现更精细的副本路由很有帮助。如果版本允许,建议优先使用这个增强版本。
典型应用场景与代码实践
第一个场景是代理层Key路由。假设你用Java实现了一个Redis代理,客户端的命令先到代理,代理需要根据Key计算哈希决定转发到哪个分片节点。核心逻辑是先解析出Key,再取第一个Key做路由。示例代码如下:
Jedis jedis = new Jedis("127.0.0.1", 6379);
// 客户端发来的原始命令参数
List<String> args = Arrays.asList("SET", "user:1001", "tom", "EX", "60");
// 用COMMAND GETKEYS解析Key
List<String> keys = jedis.commandGetKeys(args);
if (keys != null && !keys.isEmpty()) {
// 按第一个Key做一致性哈希路由
String targetNode = consistentHash.get(keys.get(0));
forwardTo(targetNode, args);
}第二个场景是命令审计。安全要求较高的系统可能需要记录所有访问了特定前缀Key的命令。可以在代理层拦截每条命令,用COMMAND GETKEYS提取Key,匹配到敏感前缀(比如token:、pay:)时落审计日志。相比在客户端逐个埋点,这种集中式方案对业务代码零侵入。
第三个场景是集群客户端的教学与调试。很多初学者不理解为什么Redis Cluster下MSET的多个Key必须落在同一个槽位,通过COMMAND GETKEYS配合CLUSTER KEYSLOT可以直观演示:先提取Key,再分别计算槽位,槽位不同就自然明白了限制的由来。
使用时有几点注意事项。一是性能,虽然单次调用开销不大,但在高流量代理中每条命令都调用一次会产生可观的压力,建议在本地缓存命令到Key位置的解析结果,只对未命中缓存的命令请求服务端。二是版本兼容,COMMAND GETKEYS要求Redis 2.8及以上,老版本环境需降级为COMMAND INFO手动解析。三是不要用它处理EVAL/EVALSHA,这类命令的Key是通过KEYS数组显式声明的,应该解析脚本调用参数而非依赖GETKEYS。
总结来看,COMMAND GETKEYS把Key定位这件事从客户端猜测变成了服务端权威回答,配合COMMAND INFO的元信息字段和7.0的GETKEYSANDFLAGS增强,几乎可以覆盖所有命令形态。理解它的能力边界,再结合缓存和手动推算做兜底,就能在代理、审计、路由等基础设施中稳定地用起来。
RedisCOMMAND GETKEYSKey提取修改时间:2026-09-10 21:54:41