首页 > 数据库 >Redis Slowlog使用与实现原理详解

Redis Slowlog使用与实现原理详解

来源:互联网 2026-07-24 09:07:45

说明 简单来说,slowlog 是 Redis 专门记录“慢查询”的日志模块。它只关注命令本身的实际执行时长,不包含客户端网络传输、回复发送等 IO 开销——换句话说,记录的是从命令开始执行到执行完毕的纯运算耗时。 很贴心的一点是,slowlog 的数据直接保存在内存中,读写速度极快。因此,即使频繁

说明

简单来说,slowlog 是 Redis 专门记录“慢查询”的日志模块。它只关注命令本身的实际执行时长,不包含客户端网络传输、回复发送等 IO 开销——换句话说,记录的是从命令开始执行到执行完毕的纯运算耗时。

Redis Slowlog使用与实现原理详解

长期稳定更新的攒劲资源: >>>点此立即查看<<<

很贴心的一点是,slowlog 的数据直接保存在内存中,读写速度极快。因此,即使频繁查询慢日志,也不会对 Redis 性能造成明显影响。

配置

slowlog 的配置主要围绕两个参数:

  • slowlog-log-slower-than:只有执行时间超过该阈值(单位微秒)的命令才会被记录。例如设为 10000,表示只记录耗时 10 毫秒以上的命令。
  • slowlog-max-len:最多保留的慢日志条数。超过该长度时,自动删除最旧的日志,避免列表无限膨胀。

配置方式有两种:

  1. 直接修改 Redis 配置文件中的 slowlog-log-slower-thanslowlog-max-len 参数,重启后生效。
  2. 运行时通过 CONFIG SET 命令动态调整,例如 CONFIG SET slowlog-log-slower-than 20000,即时生效,无需重启。

命令

与 slowlog 相关的操作命令很简洁:

  • SLOWLOG LEN:查看当前 slowlog 列表中一共有多少条记录。
  • SLOWLOG RESET:清空所有慢日志,相当于重置计数器。
  • SLOWLOG GET [count]:返回指定数量的慢日志条目,默认返回 10 条。每条日志包含:唯一 ID、时间戳、执行耗时(微秒)、命令及参数、客户端 IP 和端口、客户端名称。

实现

底层实现上,slowlog 采用一个链表(list)来存储日志条目。当一条命令执行完毕后,Redis 会调用 call() 函数,其中有一个关键判断:如果当前不是在加载 AOF 的上下文中,并且客户端没有被阻塞,就调用 slowlogPushCurrentCommand() 决定是否将这条命令写入慢日志。

核心代码如下:

void call(client *c, int flags) {
    //如果当前在 AOF 加载上下文,不要写 slowlog / latency / INFO stats
    int update_command_stats = !isAOFLoadingContext();
    //......
    if (update_command_stats && !(c->flags & CLIENT_BLOCKED))
        slowlogPushCurrentCommand(c, real_cmd, c->duration);
    //......
}

void slowlogPushCurrentCommand(client *c, struct redisCommand *cmd, ustime_t duration) {
    //是否需要纪录slowlog
    if (cmd->flags & CMD_SKIP_SLOWLOG)
        return;
    robj **argv = c->original_argv ? c->original_argv : c->argv;
    int argc = c->original_argv ? c->original_argc : c->argc;
    slowlogPushEntryIfNeeded(c,argv,argc,duration);
}

真正写入链表的逻辑在 slowlogPushEntryIfNeeded() 函数中:

void slowlogPushEntryIfNeeded(client *c, robj **argv, int argc, long long duration) {
    //判断slowlog_log_slower_than配置是否小于0,是否记录日志
    if (server.slowlog_log_slower_than < 0) return; /* Slowlog disabled */
    //如果执行时间大于slowlog_log_slower_than时间 追加到slow log list头部中
    if (duration >= server.slowlog_log_slower_than)
        listAddNodeHead(server.slowlog,
                        slowlogCreateEntry(c,argv,argc,duration));
    //判断slow log list长度是否大于slowlog_max_len,
    //如果大于slowlog_max_len 删除list尾部元素
    /* Remove old entries if needed. */
    while (listLength(server.slowlog) > server.slowlog_max_len)
        listDelNode(server.slowlog,listLast(server.slowlog));
}

流程很清晰:首先检查 slowlog_log_slower_than 是否被设为负数(负数表示禁用慢日志);如果未禁用,且命令执行时间大于等于阈值,就在链表头部插入一条新日志;最后检查链表长度是否超过 slowlog_max_len,如果超了,就反复从尾部删除最旧的记录,直到长度符合上限。

这种设计让读写都很快——插入在头部,删除在尾部,都是 O(1) 操作。由于日志存储在内存中,获取慢日志时无需磁盘 IO,非常适合在线排查性能问题。

侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述

热游推荐

更多
湘ICP备14008430号-1 湘公网安备 43070302000280号
All Rights Reserved
本站为非盈利网站,不接受任何广告。本站所有软件,都由网友
上传,如有侵犯你的版权,请发邮件给xiayx666@163.com
抵制不良色情、反动、暴力游戏。注意自我保护,谨防受骗上当。
适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。