我们都知道,使用stats命令可以对memcached的运行状况进行统计,这些统计信息包括全局的命令数统计、time统计、slab统计和connection统计等。
除了这些全局的统计信息,stats命令其实还有一些隐藏选项,能够进行KEY_PREFIX级别的细粒度统计。
之所以说是隐藏选项,是因为在官方了memcached protocol中并没有明确地说明这一用法,小生也是在阅读memcached源码是发现的,后来上网一搜,果然存在。
所谓KEY_PREFIX,是指如果你在定义key的格式时,使用冒号':'作为分隔符的话,那么冒号左边的部分就叫做KEY_PREFIX,例如:
user:12345
其中:左边的user就是KEY_PREFIX,KEY_PREFIX可以用来表示同一类数据,而:右边的12345就是该条数据的一个identifier.
使用这种格式的key之后,你就可以对每个KEY_PREFIX及每一类数据进行详细统计了,使用如下命令:
stats detail [on|off|dump]
stats detail命令顾名思义,它有三个选项:
on: 打开detail统计,即设置stats_detail_on=true
off: 关闭detail统计
dump: 输出detail统计信息,展示了每个KEY_PREFIX对应的get/hit/set/del计数,输出格式为:
stats detail dump
PREFIX user get 10 hit 9 set 1 del 0
PREFIX blog get 100 hit 98 set 2 del 1
...
基于这些更加详细的统计信息,就可以在程序上对cache的使用情况进行相应的调整,优化命中率和cache使用率。但是由于打开stats_detail_on后,每个memcached操作(set/get等)都需要调用统计代码,且如果你的memached在编译时打开了多线程选项的话,那么在统计代码中会有加锁操作,这可能在一定程度上影响memcached的性能。至于这个影响在究竟有多大,在并发请求量达到什么程度的时候才会暴露出来,小生目前尚未评估,在将来的文章中可能会提及。
附录:
memcached 1.4.5中的相关代码
1
//Memcached.c line 1181
2
if
(
strcmp
(subcommand,
"detail"
) == 0) {
3
if
(ntokens < 4)
4
process_stats_detail(c,
""
);
/* outputs the error message */
5
else
6
process_stats_detail(c, tokens[2].value);
7
return
;
8
}
01
//Memcached.c line 999
02
inline
static
void
process_stats_detail(conn *c,
const
char
*command) {
03
assert
(c != NULL);
04
05
if
(
strcmp
(command,
"on"
) == 0) {
06
settings.detail_enabled = 1;
07
out_string(c,
"OK"
);
08
}
09
else
if
(
strcmp
(command,
"off"
) == 0) {
10
settings.detail_enabled = 0;
11
out_string(c,
"OK"
);
12
}
13
else
if
(
strcmp
(command,
"dump"
) == 0) {
14
int
len;
15
char
*stats = stats_prefix_dump(&len);
16
write_and_free(c, stats, len);
17
}
18
else
{
19
out_string(c,
"CLIENT_ERROR usage: stats detail on|off|dump"
);
20
}
21
}
See also:
《使用stats detail命令进行memcached的细粒度统计》 at X-Geeker
《使用stats detail命令进行memcached的细粒度统计》 at X-Geeker on Google App Engine