01。前言相信很多朋友在使用Redis的时候都知道Redis有一个查询慢日志相关的功能,也多多少少见过。那么如果创建慢日志,Redis的底层是什么,慢日志的结构是怎样的呢?本文将带你了解它。我们先来看一张慢日志的截图,使用slowlogget2命令查看最近的两条慢日志信息。如上图所示,我们可以看到每条日志包含的信息由六部分组成,从上到下依次编号为0-5,依次表示0:日志的唯一编号ID1:命令的当前时间戳execution2:命令执行耗时,单位微妙3:具体执行命令及参数4:客户端的ip和端口(4.0以上版本)5:客户端名称(支持4.0以上版本)如图上图,第一个slowlog的id是41,命令执行的时间戳是1575729996,已经执行了16129分钟,具体执行的命令是slowlogget,ip和port是27.38.56.88:8223,client的名称未设置。02.slowlog命令设置查看上面我们已经大致知道的slowlog的格式命令。自然而然,我们能想到的问题就是一条命令执行多长时间,我们可以认为是慢查询,慢日志最多能保存多少条。我们可以通过configgetslowlog-log-slower-than命令查看Redis的持续时间设置,通过configgetslowlog-max-len命令查看慢日志条目的最大条数。如下所示。设置命令上面我们使用configget命令查看时长设置和记录条数设置。相反,我们可以使用configset来设置相关参数,如下图所示。我们先检查一下配置,然后通过configsetslowlog-log-slower-than1000命令和configsetslowlog-max-len64命令来设置具体的值:通过上面的操作我们可以看到相关的配置已经完成改变并生效。slowlog-log-slower-than:该参数表示任何超过这个时间的命令执行都会被记录为慢日志,单位为微秒。slowlog-max-len:该参数表示记录慢日志的最大数量。设置该值后,当有新的日志加入时,ID最小的日志将被删除。为了验证上面的第二点,我将slowlog-log-slower-than设置为10微秒,将slowlog-max-len设置为5进行实验。一、第一次使用slowlogget命令查询时,5条慢日志的编号从83-87,再次使用slowlogget命令查询结果为84-88,说明ID为83的已被删除。03.慢日志存储结构structredisServer{longlongslowlog_entry_id;//下一条慢查询日志的IDlist*slowlog;//保存所有慢查询日志的链表longlongslowlog_log_slower_than;//服务器配置slowlog-log-slower-thanoptionValueunsignedlongslowlog_max_len;//服务器配置的slowlog-max-len的值}在Redis服务器状态下,保存了slowlog_entry_id的相关属性。slowlog_entry_id属性的初始值为0,每创建一条慢日志就会加1。所有慢日志都存储在slowlog链表中。链表由slowlogEntry结构组成,每个slowlogEntry代表一个慢日志。slowlog_log_slower_than和slowlog_max_len是之前服务器配置的相关参数。slowloglinkedlisttypedefstructslowlogEntry{longlongid;//唯一标识time_ttime;//命令执行的时间,格式为unix时间戳longlongduration;//命令消耗的时间,单位微秒robj**argv;//命令及命令参数intargc;//命令数量及命令参数}slowlogEntry;image-20191211220858341slowlogEntryslowlogEntry实体相关字段含义如下:id:标识慢日志的唯一IDtime:命令执行时长的时间戳:命令执行耗时,单位为微秒agrv:命令和参数数组argc:命令和参数个数如上图所示,在执行第520号命令集时出现慢日志,命令执行耗时10微秒。04.操作slowlog知道了slowlog的存储结构,我们就需要考虑在执行命令时如何根据条件创建slowlog。首先我们需要记录命令执行前后的时间戳,然后减去它计算出命令的执行时间,然后根据Redis服务器配置slowlog-log-slower-than进行比较决定是否记录慢日志。另外,在记录slowlog时,有时需要根据slowlog_max_len的值来判断是否删除最早的日志信息。伪代码如下://1.记录命令执行前的时间戳longbefore=now();//2.执行命令execute(argv,argc);//3.记录命令执行后的时间戳longafter=now();//4.调用慢日志创建函数slowlogPushEntryIfNeed(argv,argc,after-before);slowlogPushEntryIfNeed函数主要用来判断是否插入数据,是否删除旧数据。voidslowlogPushEntryIfNeed(robj**argv,intargc,longlongduration){//1.判断是否开启慢日志if(server.slowlog_log_slower_than<0)return;//2.如果超时,则插入慢日志一个超时参数,如果超时参数小于0则直接返回,否则比较命令执行时间Timeout,如果超时则插入慢日志;最后检查慢日志条数是否达到上限,如果达到则删除。05.小结日常工作中经常会用到Redis,还有很多细节需要我们慢慢研究和学习。后续还会有其他相关文章,欢迎关注。
