Redis(1.18)redis阻塞分析

读书笔记《redis开发与运维》

1. 发现阻塞

    客户端记录redis相关日志时,需要具体到redis节点,在出现连接相关异常时能定位的具体节点。

    服务器端应利用相关工具加强对redis集群的监控,发现不正常指标时应进行报警,并快速反应。主要监控指标为慢查询、持久化阻塞、连接拒绝、CPU内存网络磁盘使用过载。

    阻塞出现的原因主要包括内在原因和外在原因2方面。

2. 内在原因

2.1 API或数据结构使用不合理

    通常redis执行指令的速度非常快,但有些指令如hgetall在遇到大并发且大对象时,执行速度会变慢。因此在高并发场景,避免在大对象上执行算法复杂度高的指令。

如何发现慢查询?如何发现大对象?

      slowlog get {n} 获取最近的N条慢查询指令。

      redis-cli -h{ip} -p{port} --bigkeys 指令,汇总大对象的键以及不同类型数据结构的使用情况。

      

 

 

    解决方案:

    避免使用复杂度高的指令

    根据业务合理调整大对象,将大对象拆分成多个小对象

    如果使用管道,减少管道指令数量,如果使用批量操作,减少批量操作的数量

2.2 CPU饱和

    redis是一个单线程架构,处理命令只会用一个CPU,可以使用

  redis-cli -h{ip} -p{port} --stat

 获取redis使用情况。如下图所示:

     

 

 

    上图的并发量达到6w+,优化余地不大,可以考虑扩容。如果只有几百几千的并发量redis的CPU就接近饱和是很不正常的。

    有可能是因为过度的内存优化,导致CPU执行指令变慢,如使用 info commandstats 统计指令的开销时间,如下所示:

    hset指令平均执行时间为135毫秒,肯定不合理,有可能是redis过度放宽了ziplist的使用,如调大了 hash-max-ziplist-entries和hash-max-ziplist-value配置,ziplist编码省空间,但执行效率会比hashtable低。

2.3 持久化阻塞

        fork阻塞:在RDB和AOF重写时,redis主线程会开启一个fork子进程,由子进程完成持久化操作,可以通过info stats获取到latest_fork_usec指标,如果超过1秒,则需要作出优化调整。

        AOF刷盘阻塞:开启AOF后,后台线程每秒对AOF文件做同步,如果同步超过2秒,redis会阻塞等待。也可以查看info persistence统计中的aof_delayed_fsync指标。

        hugepage写操作阻塞:具体见学习笔记8

    

fork问题

  一般是内存配置和使用问题

  fork 应该是每GB数据20毫秒左右的消耗,具体可以在 Info stats 统计中查看  latest_fork_usec 指标获取最近一次fork操作的耗时,单位毫秒。

如何改善:

  (1)使用物理机或高效的支持redis的虚拟化技术,避免使用xmen等低效虚拟化技术

  (2)控制redis 单实例的最大可用内存,fork耗时和内存数据量大小成正比

  (3)合理分配内存,要比较大,避免内存不足 fork 执行失败

  (4)控制好fork的频率,比如 rdp 的频率,aof 的同步频率,避免不必要的全量复制。

 

Aof 追加阻塞、刷盘阻塞

  一般是磁盘IO负载问题

  通过 info persistence 统计,指标 aof_delayed_fsync 指标累加

3. 外在原因

3.1 CPU竞争

    redis是CPU密集型应用,不建议和其它CPU密集服务部署在一起,因为其它CPU密集服务可能会与redis竞争CPU,可通过top、sar等命令定位CPU消耗的时间点和具体进程。

    如果把redis进程绑定到CPU上,可用于降低CPU上下文切换,但如果开启了持久化,那么fork进程会和redis进程竞争CPU,因此对于开启了持久化或参与复制的节点不要绑定CPU。

3.2 内存交换

    redis高性能的保证是所有数据都在内存中,如果redis的部分内存是虚拟内存(磁盘),那么性能急速下降,可通过如下办法查询:

    获取redis进程号: redis-cli -p 6383 info server | grep process_id

    根据进程号查询内存交换信息:cat /proc/4476/smaps | grep Swap

    如果为0,则表示内存没有被交换,预防方法如下:

        保证机器有足够的可用内存。

        设置redis实例最大可用内存即maxmemory,防止redis内存不可控的增长

        降低系统使用swap优先级

3.3 网络问题

        3.3.1 连接拒绝

            网络问题:尽量避免让redis和客户端异地跨机房调用。

            连接数控制:通过redis的maxclients控制客户端最大连接数,info stats指令的 rejected_connections 指标记录被拒绝的连接,默认最大连接是10000,超过最大连接数新连接会被拒绝。

            连接溢出--进程限制:使用Linux的ulimit -n查看系统对请求并发的控制,一般这个值需要调大,如ulimit -n 65535

            Linux操作系统请求队列限制:backlog队列溢出,操作系统对于特定端口的TCP连接使用backlog队列保存。

      修改redis的 tcp-backlog 参数,默认为511,这个参数可以理解为redis在操作系统层面能接收到的请求队列长度。可以使用指令 netstat -s |grep overflowed  查看是否出现队列溢出情况

      要修改tcp-backlog  也要同时修改系统的 /proc/sys/net/core/somaxconn 参数

        3.3.2 网络延迟、流量监控

          主要是指带宽不能满足高并发的要求,如机器网卡带宽、交换机带宽、专线带宽等。

    带宽占用主要根据当时使用率是否达到瓶颈有关,如频繁操作Redis的大对象对于redis所在的机器很容易达到网卡瓶颈,因此需要重点监控机器流量。

    网络延迟可以通过,redis-cli -h {host} -p {port} 

      --latency:持续进行延迟测试,分别统计:最小值、最大值、平均值、采样次数

      --latency-history:统计结果同 --latency,但默认每15秒完成一行统计,可以通过 -i 控制采样时间

      --latency-dist:使用统计图的形式展示延迟统计,每1S一次。

        3.3.3 网卡软中断

        网卡软中断是指由于单个网卡队列只能使用一个CPU,高并发下网卡数,据交互都集中在同一个CPU,导致无法充分利用多核CPU的情况。

     网卡软中断瓶颈一般出现在网络高流量吞吐的场景,如下使用“top+数字1”命令可以很明显看到CPU1的软中断指标(si)过高:



posted @ 2020-07-21 10:03  郭大侠1  阅读(664)  评论(0编辑  收藏  举报