Redis慢查询日志

前言

Redis的命令有一个生命周期, 比如发送一个set key value命令.

  1. Redis客户端发送set key valueRedis服务端
  2. 因为Redis是单线程, 所以命令在队列中排队.
  3. Redis服务端执行set key value命令, 并产生结果
  4. Redis服务端将结果发送给Redis客户端

Redis命令的慢查询命令就是Redis服务端消耗时间较长的命令, 耗时过长是导致客户端超时的原因之一.

慢查询配置

慢查询其实就是一个固定长度的FIFO队列, 它保存在内存中.
既然是FIFO, 那么肯定会存在旧的慢查询丢失问题, 所以需要定期进行持久化到硬盘.

修改配置文件重启(不推荐)

Redis配置文件在/etc/redis.conf下, 里面有两个属性.

1
2
3
4
# 超过 10000 微秒的命令会被记录下来, 为0则记录所有命令, 为负数则禁用慢查询日志
slowlog-log-slower-than 10000
# 慢查询日志队列长度, slowlog reset 命令会清空队列回收内存
slowlog-max-len 128

实际我们不这样做, 因为Redis支持动态配置.

动态配置

Redis可以通过命令, 将配置写入内存中, 再调用config rewrite回写到配置文件中.

1
2
3
4
5
6
7
8
redis-cli
# 慢查询日志队列长度, slowlog reset 命令会清空队列回收内存
config set slowlog-max-len 256
config get slowlog-max-len
# 超过 20000 微秒的命令会被记录下来, 为0则记录所有命令, 为负数则禁用慢查询日志
config set slowlog-log-slower-than 20000
config get slowlog-log-slower-than
config rewrite

注意! 如果Redis Server启动时没有指定配置文件, 则config rewrite会报错!

所以需要指定配置文件

1
redis-server /etc/redis.conf

Docker 配置

如果是Docker启动的话, Image里是没有redis.conf的, 需要自己映射volume.

1
2
3
4
5
6
7
# 1. 准备外部文件
mkdir /opt/docker/redis/{conf,data} -p
cp /etc/redis.conf /opt/docker/redis/redis.conf
cd /opt/docker/redis

# 2. 映射到容器内
docker run -p 6380:6379 -v $PWD/data:/data -v $PWD/conf/redis.conf:/etc/redis/redis.conf -d redis redis-server /etc/redis/redis.conf

如果是Docker-Compose启动的话, 需要指定volume, 然后后台启动docker-compose up -d.

1
2
3
4
5
6
7
8
9
10
11
12
# https://github.com/docker-library/redis/issues/125#issuecomment-363322332
version: '3'
services:
redis:
image: redis
ports:
- "6379:6379"
volumes:
- redis-data:/data
- ./conf/redis.conf:/etc/redis/redis.conf
volumes:
redis-data:

慢查询命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 1. 查看慢查询里前100条命令, 注意这里是FIFO
slowlog get 100;
# 2. 记录超过0毫秒的命令, 即所有命令记录下来
config set slowlog-log-slower-than 0
# 3. 执行命令
set k1 v1
# 4. 查看慢查询里前100条命令, 注意这里是FIFO
slowlog get 100
# 1) 1) (integer) 1
# 2) (integer) 1549684719
# 3) (integer) 141
# 4) 1) "set"
# 2) "k1"
# 3) "v1;"
# 5) "172.17.0.1:56592"
# 6) ""
# 5. 清空慢查询队列
slowlog reset

可以看到慢查询日志由6个部分组成。官方文档

条目 说明
1 (integer) 1 慢查询日志的id, 自增
2 (integer) 1549684719 开始命令的unix时间戳
3 (integer) 141 执行命令消耗的时间, 以微秒为单位
4 1) "set" 2) "k1" 3) "v1;" 组成命令的参数, 以数组形式存放
5 "172.17.0.1:56592" 4.0+新增, 客户端的ip:port
6 "" 4.0+新增, 客户端的名称

最佳实践

1
2
3
4
# 不要设置过大, 默认10ms, 通常设置1ms
config set slowlog-max-len 1
# 不要设置过小, 通常设置1000左右
config set slowlog-log-slower-than 1000

慢查询日志是一个FIFO队列, 如果一段时间没有处理, 则旧的慢查询日志则会从队列移除, 所以我们需要定期持久化慢查询日志到硬盘, 通过定时任务插入MySQL等方式.

1
slowlog get 100

参考资料