参考:
- <<Redis设计与实现>>
- 注:这本书是基于Redis3.0版本写的,和后面的版本有点差异
- http://www.redis.cn/commands/slowlog.html
Redis慢查询日志功能:记录执行时间超过给定时长的命令请求,用户可以通过这个功能产生的日志来监视和优化查询速度。
(1)服务器配置中和慢查询相关的两个属性:
slowlog-log-slower-than
:执行超过指定时间的命令请求会被记录到日志,单位:μs(微秒)。slowlog-max-len
:服务器最多保存慢查询记录数。- 若服务器存储的慢查询日志已经大于等于该值,则添加一条新的慢查询日志时,会把最早的一条记录删除。
(2)查看、设置属性值:
- 查看、设置默认值
- 在redis.conf配置文件中,
slowlog-log-slower-than 10000
、slowlog-max-len 128
两个选项设置了默认值
- 在redis.conf配置文件中,
- 服务器运行期间查看、设置这两个属性的值
- 通过
config get slowlog-log-slower-than
、config get slowlog-max-len
命令查看目前所设置的值, - 通过
config set slowlog-log-slower-than
、config set slowlog-max-len
命令设置这两个属性的值。
- 通过
(3)示例:
redis> config get slowlog-log-slower-than
1) "slowlog-log-slower-than"
2) "10000"
reids> config get slowlog-max-len
1) "slowlog-max-len"
2) "128"
一、慢查询日志相关命令
1.1 查看慢查询日志记录
使用slowlog get [size]
命令查看服务器保存的慢查询日志:
- slowlog get:查看所有慢查询日志(倒序)
- slowlog get 5:查看指定数量的慢查询日志(倒序)
示例:
redis> slowlog get 2
1) 1) (integer) 7
2) (integer) 1565083904
3) (integer) 478038
4) 1) "keys"
2) "KEY:OF:AD:SUMMA:PREFFIX*"
2) 1) (integer) 6
2) (integer) 1565083901
3) (integer) 477093
4) 1) "keys"
2) "KEY:OF:AD:SUMMA:PREFFIX"
每一个条目由四个字段组成:
- 慢查询日志的唯一的递增标识符
- 处理记录命令的unix时间戳
- 命令执行所需的总时间,单位:微秒
- 组成该命令的参数的数组(命令及命令参数)
注:条目ID在Redis服务器运行期间绝不会被重置,仅在Redis服务重启才重置。
1.2 获取慢查询日志的当前长度
使用命令slowlog len
可以获得慢查询日志的长度(慢查询日志个数)。
1.3 重置慢查询日志
使用命令slowlog reset
来重置慢查询日志。删除后,信息将永远丢失。
二、慢查询日志的实现
服务器状态中包含了4个和慢查询日志功能相关的属性:
- slowlog_entry_id:初始值0,每当要创建一条慢查询日志时,会使用该属性的值作为日志的id,之后程序会对这个属性+1
- slowlog:该链表保存了服务器中的所有慢查询日志,链表中每个节点保存了slowlogEntry结构,每个slowlogEntry结构代表一条慢查询日志。新创建的日志会保存到链表的头部。
- slowlog_log_slower_than:见上文
- slowlog_max_len:见上文
服务器状态结构如下:
struct redisServer {
// ...
// 下一条慢查询日志的ID
long long slowlog_entry_id;
// 保存了所有慢查询日志的链表
list *slowlog;
// 服务器配置slowlog-log-slower-than选项的值
long long slowlog_log_slower_than;
// 服务器配置slowlog-max-len选项的值
unsigned long slowlog_max_len;
// ...
}
slowEntry结构如下:
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"
上面这个日志对应的slowlogEntry结构如下:
2.1 慢查询日志命令的实现
- (1)查询流程如下:
- 遍历服务器状态(redisServer)的
slowlog
属性(链表),若slowlog get [size]
命令指定了数量,则打印该数量的慢查询日志,否则遍历整个链表
- 遍历服务器状态(redisServer)的
- (2)查询日志长度:
- 计算 服务器状态(redisServer)的
slowlog
链表的长度
- 计算 服务器状态(redisServer)的
- (3)清除日志
- 遍历 服务器状态(redisServer)的
slowlog
链表,删除日志
- 遍历 服务器状态(redisServer)的
- (4)新增日志
- 命令执行前后记录当前时间戳,计算出执行耗时,若该值 大于服务器状态的
slowlog_log_slower_than
属性设置的值,则创建一个新的日志,保存至slowlog
链表的头部 - 将服务器状态的
slowlog_entry_id
属性值+1 - 检查慢查询日志长度是否超过服务器状态的
slowlog_max_len
属性设置的值,如果是,则从slowlog
链表尾部删除一条最早的日志
- 命令执行前后记录当前时间戳,计算出执行耗时,若该值 大于服务器状态的