1、Redis阻塞的原因
1)内在原因:API乱用,数据结构乱用,CPU饱和,持久化阻塞
2)外在原因:CPU竞争,内存交换,网络延迟
2、使用们慢查询日志 slowlog get 10
1)生产环境应该设置为 1 毫秒就记录为耗时操作
2)生产环境最好把这些慢日志导入到MySQL永久保存,这样可以进行问题追踪
3)因为慢日志记录的是命令执行耗时,那么可能对某些时间复杂度高的命令废弃使用
3、发现大对象 redis-cli --bigkeys
找出5种数据结构中最大的对象,因为对象的大小和时间复杂度有直接关系,所以减小对象和废弃高复杂度的算法是一种很直接的方式。
4、CPU 饱和 redis-cli --stat
1)单线程的Redis在执行复杂命令时会把单个CPU100%使用,从而导致其他命令阻塞,这个时候使用 top 命令观察是不是 redis-server 居高不下来确认;
2)如果发现是 redis-server , 然后我们使用观察服务端请求状态来查看,redis-cli --stat 请求数如果是合理范围内(0-6万),那么我们就要查看具体命令耗时;
3)info command stats 单个命令耗时,我们做过基准测试单个命令耗时,如果1秒钟有5万的请求,那么 1*1000*1000/50000 = 20 微秒,换句话说每个命令 20 微秒之内才算正常。(有些命令应该更少,比如 exists,但是由于懒删除可能导致他非常耗时)
5、持久化阻塞
1)fork 阻塞,RDB dump 和 AOF rewrite 的时候,执行 info stats 查看 latest_fork_usec,表示最近一次 fork 的耗时(微秒),大约10ms per GB的样子,如果耗时达到 1秒,那么说明要优化。
2)AOF fsync 阻塞,其实就是 write(2)的时候要等 fsync(2)完成,如果两秒内还没有完成,那么强制执行 write(2),从而导致后面的命令执行阻塞,其一可以通过日志看到:
Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis.
或者可以通过命令 info persistence 查看 aof_delayed_fsync(Redis 4.0 没有这个属性了) 的大小,每次出现阻塞都会加1.
3)HugePage 阻塞,这个阻塞主要是在大量写操作时需要复制内存页,本来是 4K 结果要复制 2M,所以增大了 512 倍。对此对所有的数据库都应该设置 Linux 的 HugePage 为关闭
> echo never > /sys/kernel/mm/transparent_hugepage/enabled
6、CPU 竞争
以为Redis是单线程,不建议把Redis和其他CPU密集型的应用部署在同一台服务器上,否则就会出现CPU竞争从而导致Redis阻塞,对此可以使用 top 、 sar 命令查看CPU的使用。
7、内存交换
是指操作系统把Redis的使用的部分内存交换到磁盘,本来Redis的快就是因为是内存操作,所以如果改为磁盘操作,那其实是相当的慢的。可以通过如下命令查看是否Swap
>/usr/local/bin/redis-cli info | grep process_id
process_id:7117
>cd /proc/7117
>cat smaps | grep 'Swap:'
8、网络及连接数
1)Redis 应该对 client 进行空闲时间监测,如果空闲时间超过 30 分钟,应该 kill 掉。 设置 timeout
2)Redis 应该对 TCP 连接进行监测,也就是设置 tcp-keepalive = 1
3)Redis 调大 tcp-backlog 参数,默认 511 不要动,但是操作系统默认是 128 ,需要调为 511
> echo 511 > /proc/sys/net/core/somaxconn // 设置操作系统的默认连接数 511
> netstat -s | grep overflowed // 查找被backlog阻塞的连接数
4)网络延迟,这里的内容就比较多,不过都是出自客户端和服务端的网络问题。