开发者

一文搞懂Redis中的慢查询日志和监视器

目录
  • 慢查询
    • 添加新日志
      • 伪代码过程
      • slowlogPushEntryIfNeeded函数的作用
      • slowlogPushEntryIfNeeded函数的实现代码:
      • 例子
  • 监视器
    • 概述
      • 成为监视器
        • 例子
      • 向监视器发送命令信息
        • 例子

    慢查询

    添加新日志

    在每次执行命令的之前和之后,程序都会记录微妙格式的当前Unix时间戳,这两个时间戳之间的差就是服务器执行命令所耗费的时长,服务器会将这个时长作为参数之一传给slowlogPushEntryIfNeeded函数,而slowlogPushESbvoxintryIfNeeded函数则负责检查是否需要为这次执行的命令创建慢查询日志。

    伪代码过程

    # 记录执行命令前的时间
    before = unixtime_now_in_us()
    # 执行命令
    execute_command(argv, argc, client)
    # 记录执行命令后的时间
    after = unixtime_now_in_us()
    # 检查是否需要创建新的慢查询日志
    slowlogPushEntryIfNeeded(argv, argc, after - before)
    

    slowlogPushEntryIfNeeded函数的作用

    • 1.检查命令的时长是否超过slowlog-log-Sbvoxislower-than选项设置的时间, 如果是的话,就为命令创建一个新的日志,并将新日志添加到slowlog链表的表头
    • 2.检查慢查询日志的长度是否超过slowlog-max-len选项所设置的长度,如果是的话,那么将多出来的日志从slowlog链表中删除掉

    slowlogPushEntryIfNeeded函数的实现代码:

    void slowlogPushEntryIfNeeded(robj **argv, int argc, long long duration) {
    // 慢查询功能未开启,直接返回
    if (server.slowlog_log_slower_than < 0) return ;
    
    // 如果执行时间超过服务器设置的上限,那么将命令添加到慢查询日志
    if (duration >= server.slowlog_log_slower_than)
    // 新日志添加到链表表头
    listAddNodeHead(server.slowlog, slowlogCreateEntry(argv, argc, duration));
    
    // 如果日志数量过多,那么进行删除
    while (listLength(server.slowlog) > server.slowlog_max_len)
    listDelNode(server.slowlog, listLast(server.slowlog))
    
    }
    

    该函数根据传入的参数,创建一个新的慢查询日志,并将RedisServer.slowlog_entry_id的值增1

    例子

    举个例子。假设服务器当前保存的慢查询日志如图所示,如果执行以下命令:

    127.0.0.1:6379> EXPIRE msg 10086
    (integer) 1
    

    服务器在执行完这个EXPIRE命令之后,就会调用slowlogPushEntryIfNeeded函数,函数将未EXPIRE命令创建一条id为7的慢查询日志,并将这条新日志添加到slowlog链表的表头如图所示.注意,除了slowlog链表发生了变化之外,slowlog_entry_id的值也从7变为8了,之后,slowlogPushEntryIfNeeded函数发现,服务器设定的最大慢查询日志数目为5条,而服务器目前保存的慢查询日志数目为6条,于是服务器将id为2的慢查询日志删除,让服务器的慢查询日志数量回到设定好的5条

    一文搞懂Redis中的慢查询日志和监视器

    一文搞懂Redis中的慢查询日志和监视器

    一文搞懂Redis中的慢查询日志和监视器

    监视器

    概述

    通过执行MONITOR命令,客户端可以将自己变为一个监视器,实时地接收并打印出服务器当前处理的命令请求的相关信息:

    127.0.0.1:6379> MONITOR
    OK
    1713790637.787549 [0 127.0.0.1:60753] "PING"
    1713790641.908992 [0 127.0.0.1:60753] "SET" "k1" "v1"
    1713790645.044945 [0 127.0.0.1:60753] "SET" "k2" "v2"
    

    每当一个客户端服务器发送一条命令请求时,服务器除了会处理这条命令请求之外,还会将关于这条命令请求的信息发送给所有监视器,如图所示

    一文搞懂Redis中的慢查询日志和监视器

    成为监视器

    发送MONITOR命令可以让一个普通客户端变为一个监视Sbvoxi器,该命令的实现原理可以用以下伪代码来实现:

    def MONITOR():
    # 打开客户端的监视器状态
    client.flags |= REDIS_MONITOR
    
    # 将客户端添加android到服务器状态的monitors链表的末尾
    server.monitorjavascript.append(client)
    
    # 向客户端返回OK
    send_reply("OK")
    

    例子

    举个例子,如果客户端c10086向服务器发送MONITOR命令,那么这个客户端的REDIS_MONITOR标志会被打开,并且这个客户端本身会被添加到monitors链表的表尾。假设客户端c10086发送MONITOR之前,monitors链表的状态如图所示,那么在服务器执行客户端c10086发送的MONITOR命令之后,monitors链表将被更新为如图所示的状态

    一文搞懂Redis中的慢查询日志和监视器

    向监视器发送命令信息

    服务器在每次处理命令请求之前,都会调用replicationFeedMonitors函数,由这个函数将被处理的命令请求的相关信息发送给各个监视器。以下是replicationFeedMonitors函数的伪代码定义,函数首先根据传入的参数创建信息,然后将信息发送给所有监视器:

    def replicationFeedMOnitors(client, monitors, dbid,argv, argc):
    # 根据执行命令的客户端、当前数据库的号码、命令参数、命令参数个数等参数
    # 创建要发送给各个监视器的信息
    msg = create_message(client, dbid, argv, argc)
    
    # 遍历所有监视器
    for monitor in monitors:
    # 将信息发送给监视器
    send_message(monitor, msg)
    

    例子

    举个例子,假设服务器在时间1713791641.329412,根据IP为127.0.0.1、端口号为56604的客户端发送的命令请求,对0号数据库执行命令KEYS*,那么服务器将创建以下信息:

    1713791641.329412 [0 127.0.0.1:56604] "KEYS" "*"
    

    如果服务器monitors链表的当前状态如图上如c10086执行命令之后所示,那么服务器会分别将信息发送给c128、c256、c512和c10086四个监视器,如图所示

    一文搞懂Redis中的慢查询日志和监视器

    以上就是一文搞懂Redis中的慢查询日志和监视器的详细内容,更多关于Redis慢查询日志和监视器的资料请关注编程客栈(www.devze.com)其它相关文章!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新数据库

    数据库排行榜