Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
9f131c9a
Commit
9f131c9a
authored
Oct 19, 2017
by
zhaozhao.zz
Committed by
antirez
Nov 27, 2017
Browse files
LFU: add hotkeys option to redis-cli
parent
583c3147
Changes
1
Hide whitespace changes
Inline
Side-by-side
src/redis-cli.c
View file @
9f131c9a
...
...
@@ -107,6 +107,7 @@ static struct config {
char
*
pattern
;
char
*
rdb_filename
;
int
bigkeys
;
int
hotkeys
;
int
stdinarg
;
/* get last arg from stdin. (-x option) */
char
*
auth
;
int
output
;
/* output mode, see OUTPUT_* defines */
...
...
@@ -1129,6 +1130,8 @@ static int parseOptions(int argc, char **argv) {
config
.
pipe_timeout
=
atoi
(
argv
[
++
i
]);
}
else
if
(
!
strcmp
(
argv
[
i
],
"--bigkeys"
))
{
config
.
bigkeys
=
1
;
}
else
if
(
!
strcmp
(
argv
[
i
],
"--hotkeys"
))
{
config
.
hotkeys
=
1
;
}
else
if
(
!
strcmp
(
argv
[
i
],
"--eval"
)
&&
!
lastarg
)
{
config
.
eval
=
argv
[
++
i
];
}
else
if
(
!
strcmp
(
argv
[
i
],
"--ldb"
))
{
...
...
@@ -1229,6 +1232,8 @@ static void usage(void) {
" no reply is received within <n> seconds.
\n
"
" Default timeout: %d. Use 0 to wait forever.
\n
"
" --bigkeys Sample Redis keys looking for big keys.
\n
"
" --hotkeys Sample Redis keys looking for hot keys.
\n
"
" only works when maxmemory-policy is *lfu.
\n
"
" --scan List all keys using the SCAN command.
\n
"
" --pattern <pat> Useful with --scan to specify a SCAN pattern.
\n
"
" --intrinsic-latency <sec> Run a test to measure intrinsic system latency.
\n
"
...
...
@@ -2343,6 +2348,129 @@ static void findBigKeys(void) {
exit
(
0
);
}
static
void
getKeyFreqs
(
redisReply
*
keys
,
unsigned
long
long
*
freqs
)
{
redisReply
*
reply
;
unsigned
int
i
;
/* Pipeline OBJECT freq commands */
for
(
i
=
0
;
i
<
keys
->
elements
;
i
++
)
{
redisAppendCommand
(
context
,
"OBJECT freq %s"
,
keys
->
element
[
i
]
->
str
);
}
/* Retrieve freqs */
for
(
i
=
0
;
i
<
keys
->
elements
;
i
++
)
{
if
(
redisGetReply
(
context
,
(
void
**
)
&
reply
)
!=
REDIS_OK
)
{
fprintf
(
stderr
,
"Error getting freq for key '%s' (%d: %s)
\n
"
,
keys
->
element
[
i
]
->
str
,
context
->
err
,
context
->
errstr
);
exit
(
1
);
}
else
if
(
reply
->
type
!=
REDIS_REPLY_INTEGER
)
{
if
(
reply
->
type
==
REDIS_REPLY_ERROR
)
{
fprintf
(
stderr
,
"Error: %s
\n
"
,
reply
->
str
);
exit
(
1
);
}
else
{
fprintf
(
stderr
,
"Warning: OBJECT freq on '%s' failed (may have been deleted)
\n
"
,
keys
->
element
[
i
]
->
str
);
freqs
[
i
]
=
0
;
}
}
else
{
freqs
[
i
]
=
reply
->
integer
;
}
freeReplyObject
(
reply
);
}
}
#define HOTKEYS_SAMPLE 16
static
void
findHotKeys
(
void
)
{
redisReply
*
keys
,
*
reply
;
unsigned
long
long
counters
[
HOTKEYS_SAMPLE
]
=
{
0
};
sds
hotkeys
[
HOTKEYS_SAMPLE
]
=
{
NULL
};
unsigned
long
long
sampled
=
0
,
total_keys
,
*
freqs
=
NULL
,
it
=
0
;
unsigned
int
arrsize
=
0
,
i
,
k
;
double
pct
;
/* Total keys pre scanning */
total_keys
=
getDbSize
();
/* Status message */
printf
(
"
\n
# Scanning the entire keyspace to find hot keys as well as
\n
"
);
printf
(
"# average sizes per key type. You can use -i 0.1 to sleep 0.1 sec
\n
"
);
printf
(
"# per 100 SCAN commands (not usually needed).
\n\n
"
);
/* SCAN loop */
do
{
/* Calculate approximate percentage completion */
pct
=
100
*
(
double
)
sampled
/
total_keys
;
/* Grab some keys and point to the keys array */
reply
=
sendScan
(
&
it
);
keys
=
reply
->
element
[
1
];
/* Reallocate our freqs array if we need to */
if
(
keys
->
elements
>
arrsize
)
{
freqs
=
zrealloc
(
freqs
,
sizeof
(
unsigned
long
long
)
*
keys
->
elements
);
if
(
!
freqs
)
{
fprintf
(
stderr
,
"Failed to allocate storage for keys!
\n
"
);
exit
(
1
);
}
arrsize
=
keys
->
elements
;
}
getKeyFreqs
(
keys
,
freqs
);
/* Now update our stats */
for
(
i
=
0
;
i
<
keys
->
elements
;
i
++
)
{
sampled
++
;
/* Update overall progress */
if
(
sampled
%
1000000
==
0
)
{
printf
(
"[%05.2f%%] Sampled %llu keys so far
\n
"
,
pct
,
sampled
);
}
/* Use eviction pool here */
k
=
0
;
while
(
k
<
HOTKEYS_SAMPLE
&&
freqs
[
i
]
>
counters
[
k
])
k
++
;
if
(
k
==
0
)
continue
;
k
--
;
if
(
k
==
0
||
counters
[
k
]
==
0
)
{
sdsfree
(
hotkeys
[
k
]);
}
else
{
sdsfree
(
hotkeys
[
0
]);
memmove
(
counters
,
counters
+
1
,
sizeof
(
counters
[
0
])
*
k
);
memmove
(
hotkeys
,
hotkeys
+
1
,
sizeof
(
hotkeys
[
0
])
*
k
);
}
counters
[
k
]
=
freqs
[
i
];
hotkeys
[
k
]
=
sdsnew
(
keys
->
element
[
i
]
->
str
);
printf
(
"[%05.2f%%] Hot key '%s' found so far with counter %llu
\n
"
,
pct
,
keys
->
element
[
i
]
->
str
,
freqs
[
i
]);
}
/* Sleep if we've been directed to do so */
if
(
sampled
&&
(
sampled
%
100
)
==
0
&&
config
.
interval
)
{
usleep
(
config
.
interval
);
}
freeReplyObject
(
reply
);
}
while
(
it
!=
0
);
if
(
freqs
)
zfree
(
freqs
);
/* We're done */
printf
(
"
\n
-------- summary -------
\n\n
"
);
printf
(
"Sampled %llu keys in the keyspace!
\n
"
,
sampled
);
for
(
i
=
1
;
i
<=
HOTKEYS_SAMPLE
;
i
++
)
{
k
=
HOTKEYS_SAMPLE
-
i
;
if
(
counters
[
k
]
>
0
)
{
printf
(
"hot key found with counter: %llu
\t
keyname: %s
\n
"
,
counters
[
k
],
hotkeys
[
k
]);
sdsfree
(
hotkeys
[
k
]);
}
}
exit
(
0
);
}
/*------------------------------------------------------------------------------
* Stats mode
*--------------------------------------------------------------------------- */
...
...
@@ -2720,6 +2848,7 @@ int main(int argc, char **argv) {
config
.
pipe_mode
=
0
;
config
.
pipe_timeout
=
REDIS_CLI_DEFAULT_PIPE_TIMEOUT
;
config
.
bigkeys
=
0
;
config
.
hotkeys
=
0
;
config
.
stdinarg
=
0
;
config
.
auth
=
NULL
;
config
.
eval
=
NULL
;
...
...
@@ -2780,6 +2909,12 @@ int main(int argc, char **argv) {
findBigKeys
();
}
/* Find hot keys */
if
(
config
.
hotkeys
)
{
if
(
cliConnect
(
0
)
==
REDIS_ERR
)
exit
(
1
);
findHotKeys
();
}
/* Stat mode */
if
(
config
.
stat_mode
)
{
if
(
cliConnect
(
0
)
==
REDIS_ERR
)
exit
(
1
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment