redis源码笔记
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 = argv;
25 incrRefCount(argv);
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);
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->ptr,"reset")) {
78 slowlogReset();
79 addReply(c,shared.ok);
80 } else if (c->argc == 2 && !strcasecmp(c->argv->ptr,"len")) {
81 addReplyLongLong(c,listLength(server.slowlog));
82 } else if ((c->argc == 2 || c->argc == 3) &&
83 !strcasecmp(c->argv->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,&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); //返回的消息是一个类似嵌套的结构
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 }
页:
[1]