mirror of
https://github.com/fluencelabs/redis
synced 2025-03-31 14:51:04 +00:00
Merge branch 'bigkeys_scan' of git://github.com/michael-grunder/redis into unstable
This commit is contained in:
commit
55e36e1132
136
src/redis-cli.c
136
src/redis-cli.c
@ -1335,81 +1335,105 @@ static void pipeMode(void) {
|
|||||||
static void findBigKeys(void) {
|
static void findBigKeys(void) {
|
||||||
unsigned long long biggest[5] = {0,0,0,0,0};
|
unsigned long long biggest[5] = {0,0,0,0,0};
|
||||||
unsigned long long samples = 0;
|
unsigned long long samples = 0;
|
||||||
redisReply *reply1, *reply2, *reply3 = NULL;
|
redisReply *reply1, *reply2, *reply3 = NULL, *keys;
|
||||||
char *sizecmd, *typename[] = {"string","list","set","hash","zset"};
|
char *key, *sizecmd, *typename[] = {"string","list","set","hash","zset"};
|
||||||
char *typeunit[] = {"bytes","items","members","fields","members"};
|
char *typeunit[] = {"bytes","items","members","fields","members"};
|
||||||
int type;
|
int type, it=0, i;
|
||||||
|
|
||||||
printf("\n# Press ctrl+c when you have had enough of it... :)\n");
|
printf("\n# Press ctrl+c when you have had enough of it... :)\n");
|
||||||
printf("# You can use -i 0.1 to sleep 0.1 sec every 100 sampled keys\n");
|
printf("# You can use -i 0.1 to sleep 0.1 sec per 100 SCANS\n");
|
||||||
printf("# in order to reduce server load (usually not needed).\n\n");
|
printf("# in order to reduce server load (usually not needed).\n\n");
|
||||||
while(1) {
|
|
||||||
/* Sample with RANDOMKEY */
|
do {
|
||||||
reply1 = redisCommand(context,"RANDOMKEY");
|
/* Grab some keys with SCAN */
|
||||||
if (reply1 == NULL) {
|
reply1 = redisCommand(context, "SCAN %d", it);
|
||||||
fprintf(stderr,"\nI/O error\n");
|
if(reply1 == NULL) {
|
||||||
|
fprintf(stderr, "\nI/O error\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
} else if (reply1->type == REDIS_REPLY_ERROR) {
|
} else if(reply1->type == REDIS_REPLY_ERROR) {
|
||||||
fprintf(stderr, "RANDOMKEY error: %s\n",
|
fprintf(stderr, "SCAN error: %s\n", reply1->str);
|
||||||
reply1->str);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
} else if (reply1->type == REDIS_REPLY_NIL) {
|
} else if(reply1->type != REDIS_REPLY_ARRAY) {
|
||||||
fprintf(stderr, "It looks like the database is empty!\n");
|
fprintf(stderr, "Non ARRAY response from SCAN!\n");
|
||||||
|
exit(1);
|
||||||
|
} else if(reply1->elements!=2) {
|
||||||
|
fprintf(stderr, "Invalid SCAN result!\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Validate the SCAN response */
|
||||||
|
assert(reply1->element[0]->type == REDIS_REPLY_STRING);
|
||||||
|
assert(reply1->element[1]->type == REDIS_REPLY_ARRAY);
|
||||||
|
|
||||||
/* Get the key type */
|
/* Update iterator and grab pointer to keys */
|
||||||
reply2 = redisCommand(context,"TYPE %s",reply1->str);
|
it = atoi(reply1->element[0]->str);
|
||||||
assert(reply2 && reply2->type == REDIS_REPLY_STATUS);
|
keys = reply1->element[1];
|
||||||
samples++;
|
|
||||||
|
|
||||||
/* Get the key "size" */
|
/* Iterate keys that SCAN returned */
|
||||||
if (!strcmp(reply2->str,"string")) {
|
for(i=0;i<keys->elements;i++) {
|
||||||
sizecmd = "STRLEN";
|
/* Make sure we've got a string, grab it, and increment samples */
|
||||||
type = TYPE_STRING;
|
assert(keys->element[i]->type == REDIS_REPLY_STRING);
|
||||||
} else if (!strcmp(reply2->str,"list")) {
|
key = keys->element[i]->str;
|
||||||
sizecmd = "LLEN";
|
samples++;
|
||||||
type = TYPE_LIST;
|
|
||||||
} else if (!strcmp(reply2->str,"set")) {
|
|
||||||
sizecmd = "SCARD";
|
|
||||||
type = TYPE_SET;
|
|
||||||
} else if (!strcmp(reply2->str,"hash")) {
|
|
||||||
sizecmd = "HLEN";
|
|
||||||
type = TYPE_HASH;
|
|
||||||
} else if (!strcmp(reply2->str,"zset")) {
|
|
||||||
sizecmd = "ZCARD";
|
|
||||||
type = TYPE_ZSET;
|
|
||||||
} else if (!strcmp(reply2->str,"none")) {
|
|
||||||
freeReplyObject(reply1);
|
|
||||||
freeReplyObject(reply2);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Unknown key type '%s' for key '%s'\n",
|
|
||||||
reply2->str, reply1->str);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
reply3 = redisCommand(context,"%s %s", sizecmd, reply1->str);
|
/* Get the key type */
|
||||||
if (reply3 && reply3->type == REDIS_REPLY_INTEGER) {
|
reply2 = redisCommand(context, "TYPE %s", key);
|
||||||
if (biggest[type] < reply3->integer) {
|
assert(reply2 && reply2->type == REDIS_REPLY_STATUS);
|
||||||
printf("Biggest %-6s found so far '%s' with %llu %s.\n",
|
|
||||||
typename[type], reply1->str,
|
/* Get the key "size" */
|
||||||
(unsigned long long) reply3->integer,
|
if (!strcmp(reply2->str,"string")) {
|
||||||
typeunit[type]);
|
sizecmd = "STRLEN";
|
||||||
biggest[type] = reply3->integer;
|
type = TYPE_STRING;
|
||||||
|
} else if (!strcmp(reply2->str,"list")) {
|
||||||
|
sizecmd = "LLEN";
|
||||||
|
type = TYPE_LIST;
|
||||||
|
} else if (!strcmp(reply2->str,"set")) {
|
||||||
|
sizecmd = "SCARD";
|
||||||
|
type = TYPE_SET;
|
||||||
|
} else if (!strcmp(reply2->str,"hash")) {
|
||||||
|
sizecmd = "HLEN";
|
||||||
|
type = TYPE_HASH;
|
||||||
|
} else if (!strcmp(reply2->str,"zset")) {
|
||||||
|
sizecmd = "ZCARD";
|
||||||
|
type = TYPE_ZSET;
|
||||||
|
} else if (!strcmp(reply2->str,"none")) {
|
||||||
|
freeReplyObject(reply1);
|
||||||
|
freeReplyObject(reply2);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unknown key type '%s' for key '%s'\n",
|
||||||
|
reply2->str, key);
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The size command */
|
||||||
|
reply3 = redisCommand(context,"%s %s", sizecmd, key);
|
||||||
|
if (reply3 && reply3->type == REDIS_REPLY_INTEGER) {
|
||||||
|
if (biggest[type] < reply3->integer) {
|
||||||
|
printf("Biggest %-6s found so far '%s' with %llu %s.\n",
|
||||||
|
typename[type], key,
|
||||||
|
(unsigned long long) reply3->integer,
|
||||||
|
typeunit[type]);
|
||||||
|
biggest[type] = reply3->integer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
freeReplyObject(reply2);
|
||||||
|
if(reply3) freeReplyObject(reply3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((samples % 1000000) == 0)
|
if (samples && (samples % 1000000) == 0)
|
||||||
printf("(%llu keys sampled)\n", samples);
|
printf("(%llu keys sampled)\n", samples);
|
||||||
|
|
||||||
if ((samples % 100) == 0 && config.interval)
|
if (samples && (samples % 100) == 0 && config.interval)
|
||||||
usleep(config.interval);
|
usleep(config.interval);
|
||||||
|
|
||||||
freeReplyObject(reply1);
|
freeReplyObject(reply1);
|
||||||
freeReplyObject(reply2);
|
} while(it != 0);
|
||||||
if (reply3) freeReplyObject(reply3);
|
|
||||||
}
|
/* We've finished scanning the keyspace */
|
||||||
|
printf("\n# Scanned all %llu keys in the keyspace!\n", samples);
|
||||||
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
|
Loading…
x
Reference in New Issue
Block a user