redis 简单整理——阻塞问题[二十五]
前言
简单介绍一下redis的阻塞问题。
正文
Redis是典型的单线程架构,所有的读写操作都是在一条主线程中完成 的。当Redis用于高并发场景时,这条线程就变成了它的生命线。如果出现 阻塞,哪怕是很短时间,对于我们的应用来说都是噩梦。
·内在原因包括:不合理地使用API或数据结构、CPU饱和、持久化阻塞等。
·外在原因包括:CPU竞争、内存交换、网络问题等。
当Redis阻塞时,线上应用服务应该最先感知到,这时应用方会收到大 量Redis超时异常。
常见的做法是在应用方加入异常统计并通过邮件/短信/微信报警,以便及时发现通知问题。
在 实现异常统计时要注意,由于Redis调用API会分散在项目的多个地方,每个 地方都监听异常并加入监控代码必然难以维护。
这时可以借助于日志系统, 如Java语言可以使用logback或log4j。当异常发生时,异常信息最终会被日志 系统收集到Appender(输出目的地),默认的Appender一般是具体的日志文 件,开发人员可以自定义一个Appender,用于专门统计异常和触发报警逻辑。
借助日志系统统计异常的前提是,需要项目必须使用日志API进行异常 统一输出,比如所有的异常都通过logger.error打印,这应该作为开发规范推 广。其他编程语言也可以采用类似的日志系统实现异常统计报警。
然后如果是集群的话,那么如果客户端没有提供ip 地址和 端口的话,没法定位到哪台机器,那么可以修改客户端记录一下ip地址和端口号,这样方便定位。
内在原因
API或数据结构使用不合理。
CPU饱和的问题。
持久化相关的阻塞。
API或数据结构使用不合理
如对一个包含上万个 元素的hash结构执行hgetall操作,由于数据量比较大且命令算法复杂度是 O(n),这条命令执行速度必然很慢.
Redis原生提供慢查询统计功能,执行slowlog get{n}命令可以获取最近 的n条慢查询命令,默认对于执行超过10毫秒的命令都会记录到一个定长队 列中,线上实例建议设置为1毫秒便于及时发现毫秒级以上的命令。
如果命 令执行时间在毫秒级,则实例实际OPS只有1000左右。慢查询队列长度默认 128,可适当调大。慢查询更多细节见第3章。
慢查询本身只记录了命令执行 时间,不包括数据网络传输时间和命令排队时间,因此客户端发生阻塞异常 后,可能不是当前命令缓慢,而是在等待其他命令执行。需要重点比对异常和慢查询发生的时间点,确认是否有慢查询造成的命令阻塞排队。
发现慢查询后,开发人员需要作出及时调整。可以按照以下两个方向去 调整:
1.修改为低算法度的命令,如hgetall改为hmget等,禁用keys、sort等命令。
2.调整大对象:缩减大对象数据或把大对象拆分为多个小对象,防止一次命令操作过多的数据。大对象拆分过程需要视具体的业务决定,如用户 好友集合存储在Redis中,有些热点用户会关注大量好友,这时可以按时间 或其他维度拆分到多个集合中
- 如何发现大对象
Redis本身提供发现大对象的工具,对应命令:redis-cli-h{ip}- p{port}bigkeys。内部原理采用分段进行scan操作,把历史扫描过的最大对象 统计出来便于分析优化,运行效果如下:
cpu 饱和问题:
单线程的Redis处理命令时只能使用一个CPU。而CPU饱和是指Redis把 单核CPU使用率跑到接近100%。
使用top命令很容易识别出对应Redis进程的 CPU使用率。CPU饱和是非常危险的,将导致Redis无法处理更多的命令,严 重影响吞吐量和应用方的稳定性。
对于这种情况,首先判断当前Redis的并 发量是否达到极限,建议使用统计命令redis-cli-h{ip}-p{port}--stat获取当前 Redis使用情况,该命令每秒输出一行统计信息,运行效果如下:
有一种情况就是redis的确承受了太多。
另一个种情况就是redis 是过度的内存优化,这种情况有些隐蔽,需要我们根据info commandstats统计信息分析出命令不合理开销时间.
如果只有几百或几千OPS的Redis实例就 接近CPU饱和是很不正常的,有可能使用了高算法复杂度的命令。
这是因为上面的Redis实例为了追求低内存使用量,过度放宽ziplist使用条件 (修改了hash-max-ziplist-entries和hash-max-ziplist-value配置)。
进程内的 hash对象平均存储着上万个元素,而针对ziplist的操作算法复杂度在O(n) 到O(n2)之间。虽然采用ziplist编码后hash结构内存占用会变小,但是操作 变得更慢且更消耗CPU。ziplist压缩编码是Redis用来平衡空间和效率的优化 手段,不可过度使用。
持久性阻塞:
对于开启了持久化功能的Redis节点,需要排查是否是持久化导致的阻 塞。持久化引起主线程阻塞的操作主要有:fork阻塞、AOF刷盘阻塞、 HugePage写操作阻塞。
- fork 阻塞
fork操作发生在RDB和AOF重写时,Redis主线程调用fork操作产生共享 内存的子进程,由子进程完成持久化文件重写工作。如果fork操作本身耗时过长,必然会导致主线程的阻塞。
可以执行info stats命令获取到latest_fork_usec指标,表示Redis最近一次 fork操作耗时,如果耗时很大,比如超过1秒,则需要做出优化调整,如避 免使用过大的内存实例和规避fork缓慢的操作系统等
- AOF刷盘阻塞
当我们开启AOF持久化功能时,文件刷盘的方式一般采用每秒一次,后台线程每秒对AOF文件做fsync操作。
当硬盘压力过大时,fsync操作需要等待,直到写入完成。如果主线程发现距离上一次的fsync成功超过2秒,为了数据安全性它会阻塞直到后台线程执行fsync操作完成。
这种阻塞行为主要 是硬盘压力引起,可以查看Redis日志识别出这种情况,当发生这种阻塞行为时,会打印如下日志:
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指标,每次发生 fdatasync阻塞主线程时会累加。
硬盘压力可能是Redis进程引起的,也可能是其他进程引起的,可以使 用iotop查看具体是哪个进程消耗过多的硬盘资源。
- hugepage 写阻塞
子进程在执行重写期间利用Linux写时复制技术降低内存开销,因此只有写操作时Redis才复制要修改的内存页。
对于开启Transparent HugePages的 操作系统,每次写命令引起的复制内存页单位由4K变为2MB,放大了512 倍,会拖慢写操作的执行时间,导致大量写操作慢查询。
外在原因
- 进程竞争
Redis是典型的CPU密集型应用,不建议和其他多核CPU密 集型服务部署在一起。当其他进程过度消耗CPU时,将严重影响Redis吞吐 量。可以通过top、sar等命令定位到CPU消耗的时间点和具体进程,这个问 题比较容易发现,需要调整服务之间部署结构。
- 绑定CPU
部署Redis时为了充分利用多核CPU,通常一台机器部署多 个实例。常见的一种优化是把Redis进程绑定到CPU上,用于降低CPU频繁上 下文切换的开销。这个优化技巧正常情况下没有问题,但是存在例外情况:
当Redis父进程创建子进程进行RDB/AOF重写时,如果做了CPU绑定, 会与父进程共享使用一个CPU。子进程重写时对单核CPU使用率通常在90% 以上,父进程与子进程将产生激烈CPU竞争,极大影响Redis稳定性。因此 对于开启了持久化或参与复制的主节点不建议绑定CPU。
- 内存交换
内存交换(swap)对于Redis来说是非常致命的,Redis保证高性能的一 个重要前提是所有的数据在内存中。如果操作系统把Redis使用的部分内存 换出到硬盘,由于内存与硬盘读写速度差几个数量级,会导致发生交换后的 Redis性能急剧下降。识别Redis内存交换的检查方法如下:
预防:
保证机器充足的可用内存
确保所有Redis实例设置最大可用内存(maxmemory),防止极端情况 下Redis内存不可控的增长。
降低系统使用swap优先级,如echo10>/proc/sys/vm/swappiness
4.网络问题
网络问题经常是引起Redis阻塞的问题点。常见的网络问题主要有:连 接拒绝、网络延迟、网卡软中断等。
总结
1)客户端最先感知阻塞等Redis超时行为,加入日志监控报警工具可快 速定位阻塞问题,同时需要对Redis进程和机器做全面监控。
2) 阻塞的内在原因:确认主线程是否存在阻塞,检查慢查询等信息, 发现不合理使用API或数据结构的情况,如keys、sort、hgetall等。关注CPU 使用率防止单核跑满。当硬盘IO资源紧张时,AOF追加也会阻塞主线程。
3) 阻塞的外在原因:从CPU竞争、内存交换、网络问题等方面入手排 查是否因为系统层面问题引起阻塞。
redis 简单整理——阻塞问题[二十五]的更多相关文章
- python3.4学习笔记(二十五) Python 调用mysql redis实例代码
python3.4学习笔记(二十五) Python 调用mysql redis实例代码 #coding: utf-8 __author__ = 'zdz8207' #python2.7 import ...
- VMware vSphere 服务器虚拟化之二十五 桌面虚拟化之终端服务池
VMware vSphere 服务器虚拟化之二十五 桌面虚拟化之终端服务池 终端服务池是指由一台或多台微软终端服务器提供服务的桌面源组成的池.终端服务器桌面源可交付多个桌面.它具有以下特征: 1.终端 ...
- WCF技术剖析之二十五: 元数据(Metadata)架构体系全景展现[元数据描述篇]
原文:WCF技术剖析之二十五: 元数据(Metadata)架构体系全景展现[元数据描述篇] 在[WS标准篇]中我花了很大的篇幅介绍了WS-MEX以及与它相关的WS规范:WS-Policy.WS-Tra ...
- Bootstrap入门(二十五)JS插件2:过渡效果
Bootstrap入门(二十五)JS插件2:过渡效果 对于简单的过渡效果,只需将 transition.js 和其它 JS 文件一起引入即可.如果你使用的是编译(或压缩)版的bootstrap.js ...
- JAVA基础再回首(二十五)——Lock锁的使用、死锁问题、多线程生产者和消费者、线程池、匿名内部类使用多线程、定时器、面试题
JAVA基础再回首(二十五)--Lock锁的使用.死锁问题.多线程生产者和消费者.线程池.匿名内部类使用多线程.定时器.面试题 版权声明:转载必须注明本文转自程序猿杜鹏程的博客:http://blog ...
- JAVA之旅(二十五)——文件复制,字符流的缓冲区,BufferedWriter,BufferedReader,通过缓冲区复制文件,readLine工作原理,自定义readLine
JAVA之旅(二十五)--文件复制,字符流的缓冲区,BufferedWriter,BufferedReader,通过缓冲区复制文件,readLine工作原理,自定义readLine 我们继续IO上个篇 ...
- Java进阶(二十五)Java连接mysql数据库(底层实现)
Java进阶(二十五)Java连接mysql数据库(底层实现) 前言 很长时间没有系统的使用java做项目了.现在需要使用java完成一个实验,其中涉及到java连接数据库.让自己来写,记忆中已无从搜 ...
- 策略模式 Strategy 政策Policy 行为型 设计模式(二十五)
策略模式 Strategy 与策略相关的常见词汇有:营销策略.折扣策略.教学策略.记忆策略.学习策略.... “策略”意味着分情况讨论,而不是一概而论 面对不同年龄段的人,面对不同的商品,必然将会 ...
- C#学习基础概念二十五问
C#学习基础概念二十五问 1.静态变量和非静态变量的区别?2.const 和 static readonly 区别?3.extern 是什么意思?4.abstract 是什么意思?5.internal ...
- 剑指Offer(二十五):复杂链表的复制
剑指Offer(二十五):复杂链表的复制 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/bai ...
随机推荐
- 如何提高UI自动化稳定性?
1尽量使用相对路径的xpath表达式定位元素 2查找元素优先使用显示等待方式 3用例与用例之间避免产生依赖,用例可以单独运行 4用例执行结束之后要对测试场景进行还原,避免影响到其他用例的执行 5脚本执 ...
- C++ //类模板中成员函数创建时机 //类模板中成员函数和普通类中成员函数创建时机是有区别的: //1.普通类中的成员函数一开始就可以创建 //2.类模板中的成员函数在调用时才创建
1 //类模板中成员函数创建时机 2 //类模板中成员函数和普通类中成员函数创建时机是有区别的: 3 //1.普通类中的成员函数一开始就可以创建 4 //2.类模板中的成员函数在调用时才创建 5 6 ...
- Zabbix MQQT协议监控 loT设备
一. 项目背景 监控异地局域网主机(主机内有物联5G卡 可以单方面向特定的云服务器传输信息)这里采用 zabbix 5xx系列 agent2 -6.2 版本 主动模式,即客户端向服务端注册. 二. ...
- vscode中输入``自动将光标后面一个单词选中,左右加入<w>和</w>标签 - snippets 的命令调用
需求 vscode中输入``自动将光标后面一个单词选中,左右加入和标签 步骤0 准备需要安装插件 vim - 这里的点击两次按键激活的快捷键,这个插件可以设置 macros - 一次执行多个命令的插件 ...
- 基于恒玄WT250芯片的蓝牙辅听耳机方案调试总结
前记 在蓝牙辅听领域卷了几年之后.各种型号的蓝牙辅听器都做过.这次,客户需要一款性价比超高的蓝牙辅听器.经过成本以及功能考量的筛选.最终定下来使用wt250来做一款低成本的蓝牙辅听器. 硬件部分 wt ...
- 【stras-one】星念漫画下载器
原文链接:[stras-one]星念漫画下载器 - Stars-One的杂货小窝 一款将在线漫画保存到本地的下载工具 应一位蓝奏云批量下载器的用户的要求,实现了这款漫画下载的工具开发, 一直没时间,鸽 ...
- auto推导类型注意
auto推导类型忽略顶层const,不忽略底层const. 顶层const:指针或引用本身是const不可变,也就是指针指向的内存地址不可变,但指向的内存内容可变. 底层const:指针指向的内存地址 ...
- 基于Rust的Tile-Based游戏开发杂记(01)导入
什么是Tile-Based游戏? Tile-based游戏是一种使用tile(译为:瓦片,瓷砖)作为基本构建单位来设计游戏关卡.地图或其他视觉元素的游戏类型.在这样的游戏中,游戏世界的背景.地形.环境 ...
- 在 Windows 上利用Qwen大模型搭建一个 ChatGPT 式的问答小助手
本文首发于公众号:Hunter后端 原文链接:在 Windows 上利用Qwen大模型搭建一个 ChatGPT 式的问答小助手 最近 ChatGPT 式的聊天机器人比较火,可以提供各种问答功能,阿里最 ...
- FreeRTOS教程8 任务通知
1.准备材料 正点原子stm32f407探索者开发板V2.4 STM32CubeMX软件(Version 6.10.0) Keil µVision5 IDE(MDK-Arm) 野火DAP仿真器 XCO ...