redis的慢查詢日誌

慢查詢日誌
記錄最新的N條執行時間超過M毫秒的命令。慢查詢日誌保存在內存中,而不是文件中,這保證了慢查詢日誌的效率。
慢查詢日誌的條目定義
/* This structure defines an entry inside the slow log list */
/*
 * 慢查詢日誌
 */
typedef struct slowlogEntry {
    // 命令與命令參數
    robj **argv;
    // 命令與命令參數的數量
    int argc;
    // 惟一標識符
    long long id;       /* Unique entry identifier. */
    // 執行命令消耗的時間,以微秒爲單位
    // 註釋裏說的 nanoseconds 是錯誤的
    long long duration; /* Time spent by the query, in nanoseconds. */
    // 命令執行時的時間,格式爲 UNIX 時間戳
    time_t time;        /* Unix time at which the query was executed. */
} slowlogEntry;

服務器和慢查詢有關的定義
    /* slowlog */
    // 保存了全部慢查詢日誌的鏈表
    list *slowlog;                  /* SLOWLOG list of commands */
    // 下一條慢查詢日誌的 ID
    long long slowlog_entry_id;     /* SLOWLOG current entry ID */
    // 服務器配置 slowlog-log-slower-than 選項的值
    long long slowlog_log_slower_than; /* SLOWLOG time limit (to get logged) */
    // 服務器配置 slowlog-max-len 選項的值
    unsigned long slowlog_max_len;     /* SLOWLOG max number of items logged */
服務器的慢查詢存儲在一個list中,list中的每一項都是一條慢查詢日誌,較新的日誌老是保存在隊首。慢查詢日誌中保存命令的執行參數和執行時間,若是超出系統限制,參數和日誌可能被截斷。

慢查詢支持的客戶端操做
GET:獲取某條或者所有慢查詢日誌
RESET:清空慢查詢日誌
LEN:慢查詢日誌的數量

慢查詢日誌的應用
redis每執行一條命令,就會記錄命令的開始時間和結束時間,由此計算命令的執行時間。併發命令以及命令的執行時間傳遞給slowlogPushEntryIfNeeded,由slowlogPushEntryIfNeeded決定是否生成慢查詢日誌。
/* Call() is the core of Redis execution of a command */
// 調用命令的實現函數,執行命令
void call(redisClient *c, int flags)
{
    //獲取命令的執行時間
    /* Log the command into the Slow log if needed, and populate the
     * per-command statistics that we show in INFO commandstats. */
    // 若是有須要,將命令放到 SLOWLOG 裏面
    if (flags & REDIS_CALL_SLOWLOG && c->cmd->proc != execCommand)
        slowlogPushEntryIfNeeded(c->argv,c->argc,duration);
}

slowlogPushEntryIfNeeded的實現
判斷系統標誌位,並把慢查詢日誌加入到服務器的慢查詢鏈表中
/* Push a new entry into the slow log.
 *
 * 若是參數 duration 超過服務器設置的上限時間,
 * 那麼將一個新條目以 FIFO 順序推入到慢查詢日誌中。
 *
 * This function will make sure to trim the slow log accordingly to the
 * configured max length. 
 *
 * 根據服務器設置的最大日誌長度,可能會對日誌進行截斷(trim)
 */
void slowlogPushEntryIfNeeded(robj **argv, int argc, long long duration) {
    // 慢查詢功能未開啓,直接返回
    if (server.slowlog_log_slower_than < 0) return; /* Slowlog disabled */
    // 若是執行時間超過服務器設置的上限,那麼將命令添加到慢查詢日誌
    if (duration >= server.slowlog_log_slower_than)
        // 新日誌添加到鏈表表頭
        listAddNodeHead(server.slowlog,slowlogCreateEntry(argv,argc,duration));
    /* Remove old entries if needed. */
    // 若是日誌數量過多,那麼進行刪除
    while (listLength(server.slowlog) > server.slowlog_max_len)
        listDelNode(server.slowlog,listLast(server.slowlog));
}
相關文章
相關標籤/搜索