redis源码笔记 - slowlog

系统 1510 0

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
      
       }
    

redis源码笔记 - slowlog


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论