2、Redis变慢原因排查(下)

感觉Redis变慢了,这些可能的原因你查了没 ?(下)

Redis变慢排查的上一篇【感觉Redis变慢了,这些可能的原因你查了没 ?(上)】,我们是基于Redis命令为入口,比如命令使用不得当,bigkey问题,以及集中过期问题来看现象和如何进行优化处理的,认真读过的同学想必大家对这些现象和处理方式有了比较深的印象。

本期将基于存储层,比如AOF和RDB持久化、内存分配机制、系统层以及一些额外的影响因素,来看看这些情况是如何导致对Redis造成影响的!

先看下篇的大纲:
在这里插入图片描述
持久化

在服务层影响Redis性能的因素中,在存储层就涉及到持久化可能导致的影响,那到底是在什么情况下会发生呢!
在这里插入图片描述

AOF持久化到磁盘
大家可能想过没,在数据持久化方面,还有影响 Redis 性能的因素,这就是AOF 数据持久化。

这里回顾一下AOF机制和三种刷盘策略
在这里插入图片描述
Redis开启AOF后,工作原理如下:

1:客户端发送命令到服务器,在服务器在执行完一个写命令之后,会以Redis协议格式将被执行的写命令追加到服务器状态的 aof_buf 缓冲区的末尾,要是再执行一个写命令,那么会继续追加到aof_buf 缓冲区末尾,这就是追加方式

2:通过 write() 函数,将 aof_buf 缓冲区的数据写入到 AOF 文件

3:在主服务进程死循环的最后,会调用flushAppendOnlyFile函数,该函数会将aof_buf中的数据写入到内核缓冲区,然后判断使用何种策略进行同步

AOF三种刷盘机制如下图:
在这里插入图片描述
通过同种对三种刷盘机制的分析,可以看出如果一般不建议采用always刷盘方式,这个机制会严重拖慢Redis的性能

如果只是将Redis作为缓存,不计较数据丢失的话,可以使用 no方式

大多数人会选择比较折中的方案 everysec同步机制,既保证了数据安全又兼顾了性能,那这种机制就没有任何问题了吗?

方案没有最完美的,everysec同步机制同样存在导致Redis延迟变慢的情况。

AOF耗时的刷盘操作不是已经创建了一个后台线程去处理吗,怎么还会影响Redis主进程呢?

不过这里有个知识点需要注意,就是:

当后台线程(aof_fsync 线程)调用 fsync 函数同步 AOF 文件时,需要等待,直到写入完成。

当磁盘压力太大的时候,会导致 fsync 操作发生阻塞,主线程调用 write 函数时也会被阻塞。fsync 完成后,主线程执行 write 才能成功返回

也就是说压力到了磁盘IO这边,因此磁盘IO压力过大,同样可能导致Redis主进程阻塞,主进程阻塞了,自然处理用户命令变慢了

排查方式:

1:info Persistence,查看aof_delayed_fsync指标,一直在增加,说明主线程频繁出现被阻塞情况

2:系统日志会有提示信息【Asynchronous AOF fsync is taking too long …】

AOF重写
先看AOF重写机制,这个大多数朋友都很清楚了,这里再回顾一下:

• fork 出一条子线程来将文件重写,在执行 BGREWRITEAOF 命令时,Redis 服务器会维护一个 AOF 重写缓冲区,该缓冲区会在子线程创建新 AOF 文件期间,记录服务器执行的所有写命令。

• 当子线程完成创建新 AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新 AOF 文件的末尾,使得新的 AOF 文件保存的数据库状态与现有的数据库状态一致。

• 最后,服务器用新的 AOF 文件替换旧的 AOF 文件,以此来完成 AOF 文件重写操作

看起来是是很正常的,但是刷盘策略和重写机制一起就可能出现以外

127.0.0.1:6379> config get *append*
1) "no-appendfsync-on-rewrite"
2) "no"
3) "appendonly"
4) "yes"
5) "appendfsync"
6) "everysec"

我们看到redis配置可以得出以下结论:

1:Redis实例使用AOF进行持久化,appendfsync策略采用的是everysec刷盘

2:AOF的文件会越来越大,Redis还有一个rewrite策略,实现AOF文件的重写瘦身

3:但是no-appendfsync-on-rewrite的策略是 no,这就会导致在进行rewrite操作时,append fsync会被阻塞

4:而fsync阻塞,会导致Redis主进程也会阻塞

总结起来就是说,AOF重写机制和AOF持久化刷盘一起发生了,冲突了!
在这里插入图片描述
不过我们可以进行配置将 no-appendfsync-on-rewrite 设置为 yes 。这样可以避免AOF rewrite 重写期间,后台子线程不执行刷盘操作,但是在rewrite 期间会有AOF丢失的风险,需要自己权衡好利弊!

不过我看到过一个相对比较折中的方案,分享给大家:

1:给当前Redis实例添加slave节点,当前节点设置为master, 然后master节点关闭AOF,slave节点开启AOF

2:在master 节点设置将 no-appendfsync-on-rewrite 设置为 yes(避免重写时造成和fsync写磁盘的冲突)

3:为了防止AOF文件越来越大,配置在凌晨低峰期定时手动执行bgrewriteaof命令完成每日一次的AOF重写

4:为避免硬盘空间不足或者IO使用率高影响重写功能,添加磁盘空报警和IO使用率报警保障重写的正常进行

技术问题的处理方案有时候没有最完美的,往往是选择合适自己的方案

fork子进程耗时
先来看看fork是什么

fork 是unix和linux这种操作系统的一个api,而不是Redis的api,fork()用于创建一个子进程,不是子线程

有一点我们可以知道的是fork 的目的最终一定是为了不阻塞主进程来提升 Redis 服务的可用性。

而Redis 开启了后台 RDB 和 AOF rewrite 后,在执行时,都需会主进程创建出一个子进程进行数据的持久化,而这个过程会调用操作系统的fork()操作。
在这里插入图片描述
想具体了解如何进行fork的同学可以看我之前的文章分享:redis aof和rdb

Redis中fork 对内存数据的 copy-On-Write (写时复制) 机制最廉价的实现内存镜像

虚拟内存表是在 fork 的瞬间就需要分配,所以这个操作会造成主线程短时间的卡顿(停止所有读写操作),不过卡顿时间跟Redis内存使用量有关。

GB 量级的 Redis 进行 fork 操作的时间在毫秒级 如果这个Redis实例很大,CPU负载再高些,那么 fork 的耗时就会更长,甚至达到秒级,也就会严重影响 Redis 的访问响应时间

这也就是为什么fork()子进程可能导致Redis变慢的原因了

我们可以通过命令去查看延迟大小

//执行 INFO 命令,查看 latest_fork_usec ,时间微秒latest_fork_usec:15699

碎片化过大
什么是内存碎片?

你可以将内存碎片简单地理解为那些不可用的空闲内存

举个例子:操作系统为你分配了 16 字节的连续内存空间,而你存储数据实际只需要使用 12 字节内存空间,那这多余出来的 4 字节内存空间如果后续没办法再被分配存储其他数据的话,就可以被称为内存碎片
在这里插入图片描述
Redis 内存碎片产生比较常见的 2 个原因:

1、存储存储数据的时候向操作系统申请的内存空间可能会大于数据实际需要的存储空间

2、频繁修改 Redis 中的数据

我们可以通过info memory命令查看内存相关的信息,可以计算出内存碎片率

内存碎片率可通过参数计算:mem_fragmentation_ratio (内存碎片率)= used_memory_rss (操作系统实际分配给 Redis 的物理内存空间大小)/ used_memory(内存分配器为了存储数据实际申请使用的内存空间大小)

Redis清理内存碎片的方式有两种:

• Redis 4.0 以前的低版本,只能通过重启实例来解决,不能自动配置回收

• 从 4.0版本以后,提供了一种内存碎片自动回收的方法,可以通过配置动态开启碎片整理

碎片整理
注意开启内存碎片整理,有可能导致 Redis 服务性能下降

Redis 的碎片整理工作是在主线程中执行的,当其进行碎片整理时,操作系统会把多份数据拷贝到新位置以把原有空间释放出来,这会带来时间开销,而这个过程就会阻塞Redis处理请求

为了降低碎片整理带来的性能影响,Redis 为自动内存碎片整理机制提供了多个参数,具体有:

#是否开启碎片整理
activedefrag yes #碎片大小超过 500MB 时才会触发整理
active-defrag-ignore-bytes 500mb #碎片大小占操作系统分配总空间比超过 20% 时触发整理
active-defrag-threshold-lower 20#碎片整理过程占用的CPU比例不低于 15%,保证整理可以正常执行
active-defrag-cycle-min 15 #碎片整理过程占用的CPU比例不高于70%,一旦超过就暂停整理,
#避免大量的内存拷贝等整理过程占用过多的CPU进而影响正常请求
active-defrag-cycle-max 70 #碎片整理过程中,对于 HashListSetZSet 等成员集合类型一次扫描的元素数量
active-defrag-max-scan-fields 500 

在开启碎片自动整理时,一定要优先评估当前 Redis 服务的负载状态,以及应用程序可接受的响应延迟,合理设置碎片整理的参数值和回收时间段【比如放到凌晨程序定时触发】,来尽可能降低碎片整理期间对Redis服务的影响。

操作系统层Swap被使用
先来了解下什么是Swap

操作系统为了缓解内存不足对应用程序的影响,允许把一部分内存中的数据换到磁盘上,以达到应用程序对内存使用的缓冲,这些内存数据被换到磁盘上的区域,等到那些程序要运行时,再从Swap中恢复保存的数据到内存中,这就是 Swap。

在这里插入图片描述
也就是说内存中的数据被交换到了磁盘中,再次访问数据时,就需要从磁盘上读取,而我们知道访问磁盘的速度是比访问内存慢几个等级的。

Redis作为内存数据库,有个常识一定要记住:所有的数据默认都是在内存中,不存在一部分在内存一部分在磁盘中的情况,除非被迫发生了SWAP。

可以通过以下方式来查看 Redis 进程是否使用到了 Swap:

# 获取Redis 的进程 ID
[root@VM-12-10-opencloudos ~]#  redis-cli info | grep process_id
process_id:2600003# 查看 Redis Swap 使用情况
[root@VM-12-10-opencloudos ~]#  cat /proc/260003/smaps | egrep '^(Swap|Size)'Size:               1296 kB
Swap:                  0 kB
SwapPss:               0 kB
Size:                  4 kB
Swap:                  0 kB
SwapPss:               0 kB
Size:                 20 kB
Swap:                  0 kB
SwapPss:               0 kB
...

每一行 Size 表示 Redis 所用的一块内存大小,Size 下面的 Swap 就表示这块 Size 大小的内存,有多少数据已经被换到磁盘上了

如果这两个值相等,说明这块内存的数据都已经完全被换到磁盘上了

如果真的交换到了内存,对于Redis这种性能要求较高的,对这种延迟还是需要谨慎对待!

针对Swap情况可以参考以下解决方案:

• 建议将Redis的预留内存提高,可以多留个20%左右

• 单独不是Redis实例,避免和其他服务进程竞争使用内存

• 整理内存空间,释放出足够的内存供 Redis 使用,然后释放 Redis 的 Swap

总的来说这种内存余量和Swap情况还是要进行监控,毕竟不可能等到出现了问题才去查,那么只能做事后补救处理了

网络带宽被打满
Redis的性能问题,除了前面提到的各种可能影响因素之外,别忘了还有网络IO也可能存在瓶颈,如果网络存在瓶颈,一样会严重影响Redis性能的。

放在后面讲是默认我们认为网络环境是良好的,一般排查问题会从Redis服务去查,不过如果出现带宽过载情况的话,服务器在 TCP 层和网络层就会出现数据包发送延迟、丢包等情况。
在这里插入图片描述
如果因为流量确实大,那么可以考虑进行扩容,不过最好在运维层就Redis的这些指标进行监控,包括网络流量。

其他因素
除了上面主要列出的一些可能因素,这里也有一些其他可能导致影响的原因

Redis服务配置不合理
比如连接数配置啊,内存上限、前面我们讲的AOF持久化和重写的一些配置等等,合理的配置会尽量避免一些问题的出现

使用连接池
应该使用长连接操作 Redis,避免使用短连接模式,频繁的连接创建与销毁,在高QPS访问时网络开销巨大

cpu绑定进程影响
Redis是单线程模型处理处理用户需求,那么处理的吞吐、效率就会极度依赖CPU的处理能力

为了提高服务性能,降低应用程序在多个 CPU 核心之间的上下文切换带来的性能损耗,通常采用的方案是进程绑定 CPU 的方式提高性能

但是Redis的绑核操作过于复杂,对于单机多实例的管理挑战过高,不建议绑定 CPU来处理,这里也不做深入说明,我也没具体深入了解过了

总结
到这里,关于影响Redis性能的因素下篇就分享完了。

相信如果能耐心地看到这里的同学,想必你肯定已经对 Redis 的变慢该如何处理有了很大的收获,同样对Redis如何进行调优也收获很大。

但是通过上下两篇的内容发现 Redis 的性能问题,涉及到的知识点非常广,几乎涵盖了 CPU、内存、网络、甚至磁盘的方方面面。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/206120.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开发短视频矩阵实时直播需要用到哪些技术?

现在越来越多的人或公司都想开发出自己的直播网站或者直播APP,但是在技术这一块又不知道怎么下手,那么我就给大家讲一下在视频直播系统开发中要了解那些知识和技术: 在开发上需要用的技术有: 摄像头采集 音视频编解码 流媒体协议…

⭐Unity 搭建UDP客户端(01) 配合网络调试助手测试

1.接收来自服务器的消息 using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using UnityEngine;public class UDPManager:MonoBehaviour {public string recvStr; //服务器返回值public string UDPClientAddRess "192.168.2.39&q…

数字人对话系统 Linly-Talker

🔥🔥🔥数字人对话系统 Linly-Talker🔥🔥🔥 English 简体中文 欢迎大家star我的仓库 https://github.com/Kedreamix/Linly-Talker 2023.12 更新 📆 用户可以上传任意图片进行对话 介绍 Lin…

SolidWorks Simulation 有限元分析-升降架分析

问题描述:一个载重为 1800N 的升降架承受一外部水压柱筒的作用,该水压柱筒与基座上的滑块相连。 1. 打开零件。 2. 我们新建一个静应力分析的算例,如下图所示。 3. 设置材料。我们需要为模型指定模型的材料属性。点击选中模型,鼠…

Excel 分列功能

一. 需求 ⏹有一段文本,文本一共有7列。这7列文本之间的分隔符不相同 有一个空格的有多个空格的有Tab的jmw_state 和 method 之间用 & 连接 现在要求,将这段文本粘贴到Excel中,进行分列。并且需要将 jmw_state 和 method 也进行分列 也…

RabbitMQ(一)概述

1 RabbitMQ 概念 RabbitMQ 是一个消息中间件:它接受并转发消息。你可以把它当做一个快递站点,当你要发送一个包裹时,你把你的包裹放到快递站,快递员最终会把你的快递送到收件人那里,按照这种逻辑 RabbitMQ 是一个快递站…

Linux(16):认识系统服务(daemons)

什么是 daemon 与系统服务 【服务】一般的说明是【常驻在记体体中的程序,且可以提供一些系统或网络功能,那就是服务】。而服务一般的英文说法是【service】。 简单的说,系统为了某些功能必须要提供一些服务(不论是系统本身还是网络方面)&…

python基于ModBusTCP服务端的业务实现特定的client

python实现ModBusTCP协议的client是一件简单的事情,只要通过pymodbus、pyModbusTCP等模块都可以实现,本文采用pymodbus。但要基于ModBusTCP服务端的业务实现特定的client,那得看看服务端是否复杂。前面系列文章,我们学习了对服务端…

<IBM Websphere Portal>《关于IBM的Portal和WAS的说明和总结(自用笔记)》

《关于IBM的Portal和WAS的简单总结》 1 架构1.1 说明 2 常见问题2.1 LDAP链接问题2.2 启动脚本建议2.3 日志大小保留建议2.4 启动垃圾回收日志 3 日志位置 1 架构 应用服务部署架构如上: 👉192.168.66.1服务器运行的server进程有:dmgr、nodea…

SL1581降压恒压 耐压4V-30V降压5V 2A电流 外围简单,四个元器件

SL1581是一款专为降压恒压应用而设计的芯片,具有耐压4V-30V、降压5V、2A电流输出等特点,外围电路简单,仅需四个元器件。 一、芯片介绍 SL1581是一款专为降压恒压应用而设计的芯片,它采用先进的PWM控制技术,具有高效率、…

红队攻防之ActiveMQ漏洞集锦

要么拼命,要么滚回去 ActiveMQ 信息泄漏 实战 telnet x xActiveMQ Console 存在默认弱口令 实战 Apache ActiveMQ 默认开启了控制台,输入默认的账号密码admin/admin 登录成功 ActiveMQ 反序列化漏洞 实战 执行: java -jar jmet-0.1.0…

实现跨VLAN通信、以及如何配路由协议

一、如下图片: 按照拓扑图所示,为LSW1,LSW2,AR1,AR2配置IP地址,线路左侧使用小地址,右侧用大地址,交换机中使用的管理VLAN编号是99。 两个路由器的配法: 注意:首先给每两个路由器之间要在相同的…

Apache+mod_jk模块代理Tomcat容器

一、背景介绍 最近在看Tomcat运行架构原理, 正好遇到了AJP协议(Apache JServ Protocol). 顺道来研究下这个AJP协议和具体使用方法. 百度百科是这么描述AJP协议的: AJP(Apache JServ Protocol)是定向包协议。因为性能原因,使用二进制格式来传输…

西南科技大学C++程序设计实验八(多态一)

一、实验目的 1. 掌握多态性的分类; 2. 动态多态性-虚函数; 3. 理解纯虚函数的概念。 二、实验任务 1.分析以下程序,改正程序错误,写出程序输出结果,并按要求: (1)思考:输出结果中为什么类A是8个字节,类B是12个字节?分析虚函数的类的结构特点 A的字节大小为:…

导入JDBC元数据到Apache Atlas

前言 前期实现了导入MySQL元数据到Apache Atlas, 由于是初步版本,且功能参照Atlas Hive Hook,实现的不够完美 本期对功能进行改进,实现了导入多种关系型数据库元数据到Apache Atlas 数据库schema与catalog 按照SQL标准的解释,…

从 Kindle 文件中提取内容:GroupDocs.Parser V23.11

从 Kindle 文件中提取内容 2023 年 12 月 6 日 GroupDocs.Parser V23.11 增加了对 Kindle 文档格式的支持,支持从 Kindle 电子书和文档中提取文本和元数据。 GroupDocs.Parser 是一款全面的文档解析解决方案,使您能够从多种文档格式中提取文本、元数据和…

SLAM算法与工程实践——SLAM基本库的安装与使用(3):Pangolin库

SLAM算法与工程实践系列文章 下面是SLAM算法与工程实践系列文章的总链接,本人发表这个系列的文章链接均收录于此 SLAM算法与工程实践系列文章链接 下面是专栏地址: SLAM算法与工程实践系列专栏 文章目录 SLAM算法与工程实践系列文章SLAM算法与工程实践…

Linux--文件权限与shell外壳的理解

目录 一.Linux的用户与用户切换,提权 二.对文件权限的理解 1.文件权限角色的权限文件属性 2.Linux中的三种角色 3.为什么会存在所属组这个角色 4.文件属性的意义 4.1.第一个字母的意义 4.2 第2——第10个字母的意义 4.3修改文件权限的方法 三.目录权限 四…

文本润色工具有哪些,高质量的文本润色软件

在当今信息过载的时代,文本的重要性愈发凸显。即便是最精心构思的文章,若未经过仔细的润色,也难以达到最佳的表达效果。本文将专心分享文本润色工具的种类。 文本润色工具的种类 文本润色工具根据其功能和应用范围可以分为多个种类&#xff…

js/jQuery常见操作 之 jQuery操作复选框的常见问题

js/jQuery常见操作 之 jQuery操作复选框的常见问题 1. js/jQuery的其他一些常见基础操作2. 全选/全不选问题2.1 效果2.2 实现代码2.2.1 简单js实现2.2.2 jQuery实现2.2.2.1 注意语法(区别jQuery版本)2.2.2.2 完整代码实现 3. jQuery实现点击 行tr 实现ch…