• redis源码笔记 slowlog


    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 }
  • 相关阅读:
    46、Spark SQL工作原理剖析以及性能优化
    45、sparkSQL UDF&UDAF
    44、开窗函数及案例
    43、内置函数及每日uv、销售额统计案例
    42、JDBC数据源案例
    41、Hive数据源复杂综合案例
    40、JSON数据源综合案例实战
    39、Parquet数据源之自动分区推断&合并元数据
    Java 的String类
    Java学习之旅基础知识篇:面向对象之封装、继承及多态
  • 原文地址:https://www.cnblogs.com/liuhao/p/2510725.html
Copyright © 2020-2023  润新知