redis是经典的单线程架构,所有的读写操作都是在一个主线程中完成的。当redis处于高并发情况时,如果出现阻塞,哪怕是很短的时间,对于应用来说都相当严重,会出现大量的超时问题,应用出问题。
1. redis的阻塞主要包括两方面:
1.1 内在原因:不合理使用API或数据结构、CPU饱和持久化阻塞
1.2 外在原因:CPU竞争、内存交换、网络问题
1.1内在原因:
1.1.1:如何发现慢查询:slowlog get [N] 选型:N,可选,代表获取的日志条数
1.1.2:如何发现大对象:redis-cli -h {ip} -p {port} --bigkeys
1.1.3:CPU饱和问题:单线程Redis 处理命令时只能使用一个CPU,而CPU饱和是指Redis把单核CPU使用率跑到接近100%。CPU饱和导致Redis无法处理更多命令,严重影响吞吐和应用方的稳定。
如何发现CPU饱和:redis-cli -h {ip} -p {port} --stat
1.1.4:持久化相关阻塞:
a.fork阻塞: fork操作本身耗时过长,会导致主线程阻塞。
通过info stats中的latest_fork_usec指标确定(单位为微秒),表示最近一次fork操作耗时,如果耗时很大,比如超过1秒,则需要做优化调整,比如不使用过大内存实例,或者规避fork缓慢的xen虚拟机。
b.AOF刷盘阻塞:当我们开启AOF持久化功能时,文件刷盘的方式一般采用每秒一次,后台线程每秒对AOF文件做fsync操作。当硬盘压力过大时,fsync操作需要等待,直到写入完成。如果主线程发现距离上一次的fsync成功超过2秒,为了数据安全性它会阻塞直到后台线程执行fsync操作完成。这种阻塞行为主要是硬盘压力引起。后台日志会出现如下信息:
Asynchronous AOF fsync is taking too long (disk is busy). Writing the AOFbuffer without waiting for fsync to complete, this may slow down Redis.
1.2 外在原因:
1.2.1:CPU竞争:redis是经典的CPU密集型应用,不建议和其它的程序一起使用。可以使用top命令都为问题;
1.2.2:绑定CPU:优化把Redis绑定到CPU上,降低CPU频繁上下文切换。
注意:对于开启了持久化或参与复制的主节点不建议绑定CPU,防止父进程与子进程将产生激烈CPU竞争,影响Redis稳定性。
1.2.3:内存交行:定位内存交换方法:
a.查询redis进程号:redis-cli -p 6384 info server |grep process_id
b.根据进程号查询内存交换信息:cat /proc/xxxx/smaps |grep Swap
c.如果交换都是0kb或者偶尔4kb属于正常现象
d. 降低系统使用swap优先级: 修改swappiness
1.2.4:网络问题:
a. Redis连接拒绝:Redis通过maxclients参数控制客户端最大连接数,默认10000。查看info stats的rejected_connections统计指标展示被拒绝的数量。客户端访问尽量采用长连接或者连接池方 式。进程限制优化:设置ulimit -n 65535 防止 Too many Open files
b.backlog队列溢出:系统默认backlog为128,优化:使用echo 512>/proc/sys/net/core/somaxconn修改系统默认参数,如果怀疑是backlog队列溢出,队列溢出统计:
netstat-s|grepoverflowed,查看是否有持续增长的连接拒绝情况。
c.网络延时:网络延时统计:
redis-cli -h {host} -p {port} --latency
分别统计:最小值、最大值、平均值、采样次数
网络延时一般发生在跨机房部署
d.网卡软中断:单个网卡队列只能使用一个CPU,高并发下网卡数据集中在一个CPU下,导致无法利用多核CPU。网卡软中断瓶颈一般出现在网络高流量吞吐场景,top的si指标过高。
使用top 命令,按下1进行排查。