1
0
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:
antirez 2014-02-25 14:59:57 +01:00
commit 55e36e1132

@ -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);
} }
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------