Redis开发与运维学习笔记—(2)
- 2020 年 3 月 31 日
- 筆記
Redis使用了单线程架构和I/O多路复用模型来实现高性能的内存数据库服务,我们来看Redis的单线程命令处理机制。
我们同时打开三个窗口,第1个窗口输入:
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> get hello
"world"
第2窗口输入:
127.0.0.1:6379> incr counter
(integer) 1
第3个窗口输入:
127.0.0.1:6379> incr counter
(integer) 2
因为在redis中是单线程来处理命令的,所以一条命令从客户端到达服务器端之前不会被立即执行,而是会进入一个队列中,上面3个命令之间的执行顺序是不确定的,但是可以确定的是,肯定不会有两条命令被同时执行。
为什么单线程的redis还能处理得那么快?
主要原因如下:
1、redis是纯内存访问,它将所有的数据存放在内存中,内存的相应时间大约为100ns,这是redis达到每秒万级别访问的基础。
2、非阻塞I/O,redis使用epoll作为I/O多路复用技术的实现,再加上Redis自身的时间处理模型将epoll中的连接、读写、关闭都转换为时间,不在网络I/O上浪费过多的时间。
3、单线程,避免了线程切换和资源竞争。这样服务端也就没有了锁争用
慢查询分析
要了解redis的慢查询,首先需要知道redis的查询模型:

redis的查询模型分为4步:
1、发送命令
2、排队
3、执行命令
4、返回结果
redis的慢查询只统计步骤3的时间。
慢查询的2个配置参数
对于慢查询,redis配置了2个关键参数,其中第一个是慢查询的阈值:slowlog-log-slower-than和slowlog-max-len配置来解决这两个问题。其中:
第一个参数单位是微妙(1s=1000ms=1000000ns),默认值是1000,加入某个命令执行时间超过这个值,那么他就会被记录在慢查询日志中。
这里还有一点需要注意:如果设置slowlog的参数值为0,则会记录所有的命令,如果slowlog值小于0,则对于任何命令都不会记录。
slowlog-max-len指的是慢查询日志列表的最大长度,如果这个值设置为5,则当慢查询到达6的时候,最早的一个命令将被移除列表。
在redis中,有2种修改参数的方法,第一种是修改配置文件,另一种是使用config set命令动态修改,如果要将redis的配置持久化到本地的配置文件,则需要执行config rewrite的命令。我们看看参数的默认值:
[root@VM_48_10_centos redis]# cat redis.conf |grep slowlog slowlog-log-slower-than 10000 slowlog-max-len 128
当我们使用config rewrite之后,可以看到:
[root@VM_48_10_centos redis]# redis-cli 127.0.0.1:6379> config set slowlog-max-len 256 OK 127.0.0.1:6379> config rewrite 20673:M 26 Mar 23:14:58.643 # CONFIG REWRITE executed with success. OK 127.0.0.1:6379> exit [root@VM_48_10_centos redis]# cat redis.conf |grep slowlog slowlog-log-slower-than 10000 slowlog-max-len 256
已经成功的将配置写入了配置文件中了。
慢查询如何查看?
redis的慢查询是存放在redis的内存列表中的,但是redis并没有暴露这个列表的键,而是通过一组命令来实现对慢查询日志的访问和管理:
slowlog get [n]
上面的命令可以返回当前redis的慢查询,参数n可以指定条数。下面是测试例子:
[root@VM_48_10_centos redis]# redis-cli 127.0.0.1:6379> config set slowlog-log-slower-than 0 OK 127.0.0.1:6379> set hello world OK 127.0.0.1:6379> get hello "world" 127.0.0.1:6379> slowlog get 2 1) 1) (integer) 4 2) (integer) 1585235910 3) (integer) 10 4) 1) "slowlog" 2) "get" 3) "1" 2) 1) (integer) 3 2) (integer) 1585235905 3) (integer) 4 4) 1) "get" 2) "hello"
每条日志有4个属性,分别是redis慢日志的标识id、发生的时间戳、命令耗时和参数。
还有:
slowlog len命令用来查询慢查询当前的条数。
slowlog reset用来重置慢查询列表
127.0.0.1:6379> slowlog len (integer) 6 127.0.0.1:6379> slowlog reset OK 127.0.0.1:6379> slowlog len (integer) 1
我们由于配置了slowlog-log-slow..为0,所以清理之后,还会记录slowlog len本身。
几点注意:
1、线上的话,slowlog-max-len建议调大,因为记录慢查询时redis会对长命令做截断处理,所以并不会占用大量内存。线上的可以设置1000以上。
2、slowlog-log-slower-than默认值超过10ms就判定为慢查询,需要根据redis的并发量调整,如果某个应用是高并发的,如果命令执行时间在1ms以上,则OPS将不到1000,要根据实际情况来调整这个参数。
3、慢查询只记录命令的执行时间,并不包括命令排队和网络传输时间,因此客户端执行命令的时间会大于命令实际执行时间,因此当线上出现阻塞时,应当先分析慢查询,从而排除慢查询造成的阻塞。
4、因为慢查询日志是一个先进先出的队列,在慢查询比较多的情况下,可以定期执行slow get命令将慢查询日志持久化到其他存储中,然后定制可视化界面进行查询。