Redis 的慢查询日志功能用于记录执行时间超过给定时长的命令请求,用户可以同故宫这个功能产生的日志来监视和优化查询速度
redis查看慢日志、服务器配置有两个和慢查询日志相关的选项:
服务器使用先进先出的方式保存多条慢查询日志,当服务器存储的慢查询日志数量等于 slowlog-max-len 选项的值时,服务器在添加一条新的慢查询日志之前,会先将最旧的一条慢查询日志删除
服务器状态中包含了几个和慢查询日志功能有关的属性:
struct redisServer{//...//下一条慢查询日志的 IDlong long slowlog_entry_id;//保存了所有慢查询日志的链表list *slowlog;//服务器配置 slowlog-log-slower-than 选项的值long long slowlog_log_slower_than;//服务器配置 slowlog-max-len 选项的值ussigned long slowlog_max_len;//...
};
slowlog_entry_id 属性的初始值为 0,每当创建一条新的慢查询日志时,这个属性的值就会用作新日志的 id 值,之后程序会对这个属性的值增一
redis 间歇性慢?例如,在创建第一条慢查询日志时,slowlog_entry_id 的值 0 会成为第一条慢查询日志的 ID,而之后服务器会对这个属性的值增一;当服务器再创建新的慢查询日志的时候,slowlog_entry_id 的值 1 就会成为第二条慢查询日志的 ID,然后服务器再次对这个属性的值增一,以此类推
slowlog 链表保存了服务器中的所有慢查询日志,链表中的每个节点都保存了一个 slowlogEntry 结构,每个 slowlogEntry 结构代表一条慢查询日志:
typedef struct slowlogEntry{//唯一标识符long long id;//命令执行时的时间,格式为 UNIX 时间戳time_t time;//执行命令消耗的时间,以微秒为单位long long duration;//命令与命令参数robj **argv;//命令与命令参数的数量int argc;
}slowlogEntry;
举个例子,对于以下慢查询日志来说:
1)(integer) 3
2)(integer) 1378781439
3)(integer) 10
4)1)"SET"2)"number"3)"10086"
图 23-1 展示的是该日志所对应的 slowlogEntry 结构
redis大数据读取慢,
图 23-2 展示了服务器状态中和慢查询功能有关的属性:
弄清楚了服务器状态的 slowlog 链表的作用之后,我们可以用以下伪代码来定义查看日志的 SLOWLOG GET 命令:
def SLOWLOG_GET(number=None):#用户没有给定 number 参数#那么打印服务器包含的全部慢查询日志if number is None:number = SLOWLOG_LEN()#遍历服务器中的慢查询日志for log in redisServer.slowlog:if number <= 0:#打印的日志数量已经足够,跳出循环breakelse:#继续打印,将计数器的值减一number -= 1#打印日志printLog(log)
redis远程访问慢,查看日志数量的 SLOWLOG LEN 命令可以用以下伪代码来定义:
def SLOWLOG_LEN():#slowlog 链表的长度就是慢查询日志的条目数量return len(redisServer.slowlog)
另外,用于清除所有慢查询日志的 SLOWLOG RESET 命令可以用以下伪代码来定义:
def SLOWLOG_RESET():#遍历服务器中的所有慢查询日志for log in redisServer.slowlog:#删除日志deleteLog(log)
在每次执行命令的之前和之后,程序都会记录微秒格式的当前 UNIX 时间戳,这两个时间戳之间的差就是服务器执行命令所耗费的时长,服务器会将这个时长作为参数之一传给 slowlogPushEntryIfNeeded 函数,而 slowlogPushEntryIfNeeded 函数负责检查是否需要为这次执行的命令创建慢查询日志,以下伪代码展示了这一过程:
#记录执行命令前的时间
before = unixtime_now_in)us()#执行命令
execute_command(argv, argc, client)#记录执行命令后的时间
after = unixtime_now_in_us()#检查是否需要创建新的慢查询日志
slowlogPushEntryIfNeeded(argv, argc, before-after)
slowlogPushEntryIfNeeded 函数的作用有两个:
redis大量失效key慢?以下是 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)//新日志添加到链表表头listAddNodedHead(server.slowlog, slowlogCreateEntry(argv, argc, duration));//如果日志数量过多,那么进行删除while(listLength(server.slowlog) > server.slowlog_max_len)listDelNode(server.slowlog, listLast(server.slowlog));
}
函数中的大部分代码我们已经介绍过了,唯一需要说明的就是 slowlogCreateEntry 函数:该函数根据传入的参数,创建一个新的慢查询日志,并将 redisServer.slowlog_entry_id 的值增 1
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态