要遍历Redis所有key或者指定模式的key有两种方法:KEYS和SCAN
1.KEYS命令
KEYS pattern
查找所有符合给定模式pattern(正则表达式)的 key 。时间复杂度为O(N),N为数据库里面key的数量。例如,Redis在一个有1百万个key的数据库里面执行一次查询需要的时间是40毫秒 。
警告: KEYS 的速度非常快,但在一个大的数据库中使用它仍然可能造成性能问题,如果你需要从一个数据集中查找特定的 KEYS, 你最好还是用 Redis 的集合结构 SETS 来代替。
支持的正则表达模式:
h?llo 匹配 hello, hallo 和 hxllo
h*llo 匹配 hllo 和 heeeello
h[ae]llo 匹配 hello 和 hallo, 但是不匹配 hillo
h[^e]llo 匹配 hallo, hbllo, … 但是不匹配 hello
h[a-b]llo 匹配 hallo 和 hbllo
如果你想取消字符的特殊匹配(正则表达式,可以在它的前面加\。
返回值
array-reply: 所有符合条件的key
例子
redis> MSET one 1 two 2 three 3 four 4
OK
redis> KEYS *o*
1) "four"
2) "one"
3) "two"
redis> KEYS t??
1) "two"
redis> KEYS *
1) "four"
2) "three"
3) "one"
4) "two"
redis>
2.SCAN命令
SCAN cursor [MATCH pattern] [COUNT count]
SCAN命令是一个基于游标的迭代器。这意味着命令每次被调用都需要使用上一次这个调用返回的游标作为该次调用的游标参数,以此来延续之前的迭代过程。当SCAN命令的游标参数被设置为 0 时, 服务器将开始一次新的迭代, 而当服务器向用户返回值为 0 的游标时, 表示迭代已结束。
以下是一个 SCAN 命令的迭代过程示例 :
redis 127.0.0.1:6379> scan 0
1) "17"
2) 1) "key:12"
2) "key:8"
3) "key:4"
4) "key:14"
5) "key:16"
6) "key:17"
7) "key:15"
8) "key:10"
9) "key:3"
10) "key:7"
11) "key:1"
redis 127.0.0.1:6379> scan 17
1) "0"
2) 1) "key:5"
2) "key:18"
3) "key:0"
4) "key:2"
5) "key:19"
6) "key:13"
7) "key:6"
8) "key:9"
9) "key:11"
3.c语言实现Redis遍历所有key
example.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hiredis.h"
int main(int argc, char **argv) {
unsigned int i;
redisContext *c;
redisReply *reply;
const char *hostname = (argc > 1) ? argv[1] : "127.0.0.1";
int port = (argc > 2) ? atoi(argv[2]) : 6379;
char rediscmd[50] = {0};
struct timeval timeout = { 1, 500000 }; // 1.5 seconds
c = redisConnectWithTimeout(hostname, port, timeout);
if (c == NULL || c->err) {
if (c) {
printf("Connection error: %s\n", c->errstr);
redisFree(c);
} else {
printf("Connection error: can't allocate redis context\n");
}
exit(1);
}
/*使用KEYS 匹配*/
const char* command1 = "KEYS *oo";
reply = redisCommand(c,command1);
if (reply->type != REDIS_REPLY_ARRAY) {
printf("Failed to execute command[%s].\n",command1);
freeReplyObject(reply);
redisFree(c);
return;
}
for (i = 0; i < reply->elements; ++i) {
redisReply* childReply = reply->element[i];
if (childReply->type == REDIS_REPLY_STRING)
printf("The keys value is %s.\n",childReply->str);
}
freeReplyObject(reply);
/*使用SCAN匹配*/
const char* command2 = "scan 0 MATCH *oo";
reply = redisCommand(c,command2);
if (reply->type != REDIS_REPLY_ARRAY) {
printf("Failed to execute command[%s].\n",command2);
freeReplyObject(reply);
redisFree(c);
return;
}
redisReply* childReply0 = reply->element[0];
if (childReply0->type == REDIS_REPLY_STRING){
printf("The value is %s.\n",childReply0->str);
while (strcmp(childReply0->str, "0")!=0)
{
redisReply* childReply1 = reply->element[1];
for (i = 0; i < childReply1->elements; ++i) {
redisReply* childReply2 = childReply1->element[i];
if (childReply2->type == REDIS_REPLY_STRING)
printf("The scan value is %s.\n",childReply2->str);
}
/*组装redis命令*/
snprintf(rediscmd,sizeof(rediscmd),"scan %s MATCH *oo",childReply0->str);
printf("The scan rediscmd is %s.\n",rediscmd);
reply = redisCommand(c,rediscmd);
childReply0 = reply->element[0];
}
/**while (strcmp(childReply0->str, "0")==0)的情况也别忘了遍历一遍**/
redisReply* childReply1 = reply->element[1];
for (i = 0; i < childReply1->elements; ++i) {
redisReply* childReply2 = childReply1->element[i];
if (childReply2->type == REDIS_REPLY_STRING)
printf("The scan value is %s.\n",childReply2->str);
}
}
freeReplyObject(reply);
printf("Succeed to execute command[%s].\n",command2);
/* Disconnects and frees the context */
redisFree(c);
return 0;
}
编译example.c
gcc example.c -o example -lhiredis
启动redis服务器
./redis-server ../redis.conf
运行
./example
运行结果
The keys value is foo.
The keys value is zoo.
The value is 20.
The scan value is foo.
The scan rediscmd is scan 20 MATCH *oo.
The scan rediscmd is scan 30 MATCH *oo.
The scan rediscmd is scan 25 MATCH *oo.
The scan rediscmd is scan 19 MATCH *oo.
The scan value is zoo.
Succeed to execute command[scan 0 MATCH *oo].