slowlog是redis提供的進行query分析的工具。它將執行時間長的命令統一以list形式保存在內存之中,使用者可以通過slowlog命令查看這些慢query,從而分析系統瓶頸。
最好的分析筆記是作者的注釋,除此之外,會做簡要記錄。
slowlog.h
1
/*
This structure defines an entry inside the slow log list
*/
2
typedef
struct
slowlogEntry {
3
robj **
argv; //記錄query參數
4
int
argc;
5
long
long
id;
/*
Unique entry identifier.
*/
6
long
long
duration;
/*
Time spent by the query, in nanoseconds.
*/
7
time_t time;
/*
Unix time at which the query was executed.
*/
8
} slowlogEntry;
9
10
/*
Exported API
*/
11
void
slowlogInit(
void
); //在redis.c的initServer函數中被調用,初始化一個list結構,只在系統啟動時調用一次
12
void
slowlogPushEntryIfNeeded(robj **argv,
int
argc,
long
long
duration);
13
14
/*
Exported commands
*/
15
void
slowlogCommand(redisClient *c); //slowlog Command將會觸發此函數被調用
slowlog.c
1
#include
"
redis.h
"
2
#include
"
slowlog.h
"
3
4
/*
Slowlog implements a system that is able to remember the latest N
5
* queries that took more than M microseconds to execute.
6
*
7
* The execution time to reach to be logged in the slow log is set
8
* using the 'slowlog-log-slower-than' config directive, that is also
9
* readable and writable using the CONFIG SET/GET command.
10
*
11
* The slow queries log is actually not "logged" in the Redis log file //只在內存中保存
12
* but is accessible thanks to the SLOWLOG command.
*/
13
14
/*
Create a new slowlog entry.
15
* Incrementing the ref count of all the objects retained is up to
16
* this function.
*/
17
slowlogEntry *slowlogCreateEntry(robj **argv,
int
argc,
long
long
duration) {
18
slowlogEntry *se = zmalloc(
sizeof
(*
se));
19
int
j;
20
21
se->argc =
argc;
22
se->argv = zmalloc(
sizeof
(robj*)*
argc);
23
for
(j =
0
; j < argc; j++
) {
24
se->argv[j] =
argv[j];
25
incrRefCount(argv[j]);
26
}
27
se->time =
time(NULL);
28
se->duration =
duration;
29
se->id = server.slowlog_entry_id++
;
30
return
se;
31
}
32
33
/*
Free a slow log entry. The argument is void so that the prototype of this
34
* function matches the one of the 'free' method of adlist.c.
35
*
36
* This function will take care to release all the retained object.
*/
37
void
slowlogFreeEntry(
void
*
septr) {
38
slowlogEntry *se =
septr;
39
int
j;
40
41
for
(j =
0
; j < se->argc; j++
)
42
decrRefCount(se->
argv[j]);
43
zfree(se->
argv);
44
zfree(se);
45
}
46
47
/*
Initialize the slow log. This function should be called a single time
48
* at server startup.
*/
49
void
slowlogInit(
void
) {
50
server.slowlog =
listCreate();
51
server.slowlog_entry_id =
0
;
52
listSetFreeMethod(server.slowlog,slowlogFreeEntry);
53
}
54
55
/*
Push a new entry into the slow log.
56
* This function will make sure to trim the slow log accordingly to the
57
* configured max length.
*/
58
void
slowlogPushEntryIfNeeded(robj **argv,
int
argc,
long
long
duration) {
59
if
(server.slowlog_log_slower_than <
0
)
return
;
/*
Slowlog disabled
*/
60
if
(duration >=
server.slowlog_log_slower_than)
61
listAddNodeHead(server.slowlog,slowlogCreateEntry(argv,argc,duration));
62
63
/*
Remove old entries if needed.
*/
64
while
(listLength(server.slowlog) >
server.slowlog_max_len)
65
listDelNode(server.slowlog,listLast(server.slowlog));
66
} //該函數在每次命令執行時均被調用,對于非慢速的命令,只有一個分支調用的開銷;
67
68
/*
Remove all the entries from the current slow log.
*/
69
void
slowlogReset(
void
) {
70
while
(listLength(server.slowlog) >
0
)
71
listDelNode(server.slowlog,listLast(server.slowlog));
72
}
73
74
/*
The SLOWLOG command. Implements all the subcommands needed to handle the
75
* Redis slow log.
*/ slow long get (count) || slowlog reset || slowlog len
76
void
slowlogCommand(redisClient *
c) {
77
if
(c->argc ==
2
&& !strcasecmp(c->argv[
1
]->ptr,
"
reset
"
)) {
78
slowlogReset();
79
addReply(c,shared.ok);
80
}
else
if
(c->argc ==
2
&& !strcasecmp(c->argv[
1
]->ptr,
"
len
"
)) {
81
addReplyLongLong(c,listLength(server.slowlog));
82
}
else
if
((c->argc ==
2
|| c->argc ==
3
) &&
83
!strcasecmp(c->argv[
1
]->ptr,
"
get
"
))
84
{
85
long
count =
10
, sent =
0
;
86
listIter li;
87
void
*
totentries;
88
listNode *
ln;
89
slowlogEntry *
se;
90
91
if
(c->argc ==
3
&&
92
getLongFromObjectOrReply(c,c->argv[
2
],&count,NULL) !=
REDIS_OK)
93
return
;
94
95
listRewind(server.slowlog,&
li);
96
totentries =
addDeferredMultiBulkLength(c);
97
while
(count-- && (ln = listNext(&
li))) {
98
int
j;
99
100
se = ln->
value;
101
addReplyMultiBulkLen(c,
4
);
102
addReplyLongLong(c,se->
id);
103
addReplyLongLong(c,se->
time);
104
addReplyLongLong(c,se->
duration);
105
addReplyMultiBulkLen(c,se->
argc);
106
for
(j =
0
; j < se->argc; j++
)
107
addReplyBulk(c,se->
argv[j]); //返回的消息是一個類似嵌套的結構
108
sent++
;
109
}
110
setDeferredMultiBulkLength(c,totentries,sent);
111
}
else
{
112
addReplyError(c,
113
"
Unknown SLOWLOG subcommand or wrong # of args. Try GET, RESET, LEN.
"
);
114
}
115
}
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

