Redis阻塞整理笔记

Redis是典型的单线程架构,全部的读写操做都是在一条主线程中完成的。当Redis用于高并发场景时,这条线程就变成了它的生命线。若是出现阻塞,哪怕是很短期,对于应用来讲都是噩梦。redis

致使阻塞问题的缘由:算法

  • 内在缘由:不合理地使用API或数据结构、CPU饱和、持久化阻塞等
  • 外在缘由:CPU竞争、内存交换、网络问题等

 

 

 

 

1、发现阻塞sql

  • 应用方加入异常监控,如日志系统,好比Java语言中的logback或log4j
  • Redis监控系统,如CacheCloud

 

2、内在缘由安全

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

一般Redis执行命令速度很是快,可是,若是对一个包含上万个元素的hash结构执行hgetall操做,因为数据量比较大且命令算法复杂度是O(n),这条命令执行速度必然很慢。网络

对于高并发的场景应该尽可能避免在大对象上执行算法复杂度超过O(n)的命令。数据结构

(1)如何发现慢查询架构

Redis原生提供慢查询统计功能,执行slowlog get{n}命令能够获取最近的n条慢查询命令,默认对于执行超过10毫秒的命令都会记录到一个定长队列中,线上实例建议设置为1毫秒便于及时发现毫秒级以上的命令。并发

(2)发现慢查询后如何调整分布式

  • 修改成低算法复杂度的命令
  • 调整大对象:缩减大对象数据或把大对象拆分为多个小对象,防止一次命令操做过多的数据。大对象拆分过程须要视具体的业务决定,如用户好友集合存储在Redis中,有些热点用户会关注大量好友,这时能够按时间或其余维度拆分到多个集合中。

 

(3)如何发现大对象

Redis自己提供发现大对象的工具。具体命令:

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

 

内部原理采用分段进行scan操做,把历史扫描过的最大对象统计出来便于分析优化。

2.2 CPU饱和

单线程的Redis处理命令时只能使用一个CPU。而CPU饱和是指Redis把单核CPU使用率跑到接近100%。使用top命令很容易识别出对应Redis进程的CPU使用率。CPU饱和是很是危险的,将致使Redis没法处理更多的命令,严重影响吞吐量和应用方的稳定性。对于这种状况,首先判断当前Redis的并发量是否达到极限,建议使用统计命令redis-cli -h {ip} -p {port} --stat获取当前Redis使用状况

2.3 持久化阻塞

对于开启了持久化功能的Redis节点,须要排查是不是持久化致使的阻塞。

  • fork阻塞:fork操做发生在RDB和AOF重写时,Redis主线程调用fork操做产生共享内存的子进程,由子进程完成持久化文件重写工做。若是fork操做自己耗时过长,必然会致使主线程的阻塞。
  • AOF刷盘阻塞:当咱们开启AOF持久化功能时,文件刷盘的方式通常采用每秒一次,后台线程每秒对AOF文件作fsync操做。当硬盘压力过大时,fsync操做须要等待,直到写入完成。若是主线程发现距离上一次的fsync成功超过2秒,为了数据安全性它会阻塞直到后台线程执行fsync操做完成。这种阻塞行为主要是硬盘压力引发。
  • HugePage写操做阻塞:子进程在执行重写期间利用Linux写时复制技术下降内存开销,所以只有写操做时Redis才复制要修改的内存页。对于开启Transparent HugePages的操做系统,每次写命令引发的复制内存页单位由4K变为2MB,放大了512倍,会拖慢写操做的执行时间,致使大量写操做慢查询。

3、外在缘由

3.1 CPU竞争

  • 进程竞争:Redis是典型的CPU密集型应用,不建议和其余多核CPU密集型服务部署在一块儿。当其余进程过分消耗CPU时,将严重影响Redis吞吐量。能够经过top、sar等命令定位到CPU消耗的时间点和具体进程,这个问题比较容易发现,须要调整服务之间部署结构。
  • 绑定CPU:部署Redis时为了充分利用多核CPU,一般一台机器部署多个实例。常见的一种优化是把Redis进程绑定到CPU上,用于下降CPU频繁上下文切换的开销。这个优化技巧正常状况下没有问题,可是存在例外状况,当Redis父进程建立子进程进行RDB/AOF重写时,若是作了CPU绑定,会与父进程共享使用一个CPU。子进程重写时对单核CPU使用率一般在90%以上,父进程与子进程将产生激烈CPU竞争,极大影响Redis稳定性。所以对于开启了持久化或参与复制的主节点不建议绑定CPU。

 

3.2 内存交换

内存交换(swap)对于Redis来讲是很是致命的,Redis保证高性能的一个重要前提是全部的数据在内存中。若是操做系统把Redis使用的部份内存换出到硬盘,因为内存与硬盘读写速度差几个数量级,会致使发生交换后的Redis性能急剧降低。

预防内存交换:

  • 保证机器充足的可用内存。
  • 确保全部Redis实例设置最大可用内存(maxmemory),防止极端状况下Redis内存不可控的增加。
  • 下降系统使用swap优先级。

3.3 网络问题

(1)链接拒绝

  • 网络闪断(网络割接或者带宽耗尽)
  • Redis链接拒绝(超过客户端最大链接数)
  • 链接溢出(进程限制或backlog队列溢出)

(2)网络延迟

网络延迟取决于客户端到Redis服务器之间的网络环境。主要包括它们之间的物理拓扑和带宽占用状况。常见的物理拓扑按网络延迟由快到慢可分为:同物理机>同机架>跨机架>同机房>同城机房>异地机房。但它们容灾性正好相反,同物理机容灾性最低而异地机房容灾性最高。

网络延迟问题常常出如今跨机房的部署结构上,对于机房之间延迟比较严重的场景须要调整拓扑结构,如把客户端和Redis部署在同机房或同城机房等。

带宽瓶颈一般出如今如下几个方面:

  • 机器网卡带宽。
  • 机架交换机带宽。
  • 机房之间专线带宽。

(3)网卡软中断

网卡软中断是指因为单个网卡队列只能使用一个CPU,高并发下网卡数据交互都集中在同一个CPU,致使没法充分利用多核CPU的状况。网卡软中断瓶颈通常出如今网络高流量吞吐的场景。

欢迎工做一到五年的Java工程师朋友们加入Java架构开发: 855835163 群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用本身每一分每一秒的时间来学习提高本身,不要再用"没有时间“来掩饰本身思想上的懒惰!趁年轻,使劲拼,给将来的本身一个交代!

相关文章
相关标签/搜索