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

news2024/11/19 7:45:02

感觉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.coloradmin.cn/o/1294628.html

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

相关文章

Vue3组件使用问题

Vue3组件学习 文章目录 Vue3组件学习一、Message 全局提示组件返回数据换行问题二、DatePicker 日期选择框组件限制选定年份问题 一、Message 全局提示组件返回数据换行问题 问题&#xff1a;使用中发现仅仅通过写入\n或<br/>&#xff0c;无法实现回车显示的结果。 解决…

网站高性能架构设计——web前端与池化

从公众号转载&#xff0c;关注微信公众号掌握更多技术动态 --------------------------------------------------------------- 一、高性能浏览器访问 1.减少HTTP请求 HTTP协议是无状态的应用层协议&#xff0c;也就是说每次HTTP请求都需要建立通信链路、进行数据传输&#xf…

Swagger Array 逐步解密:带你简化开发工作

Swagger 允许开发者定义 API 的路径、请求参数、响应和其他相关信息&#xff0c;以便生成可读性较高的文档和自动生成客户端代码。而 Array &#xff08;数组&#xff09;是一种常见的数据结构&#xff0c;用于存储和组织多个相同类型的数据元素。数组可以有不同的维度和大小&a…

想要高速文件传输?这些Aspera替代方案等你来试

在现如今数字化的时代&#xff0c;文件传输已成为企业、组织以及个人日常工作中必不可少的一部分。但是&#xff0c;面对庞大的数据量和低效的传输速度&#xff0c;很多人会感到头疼和无奈。在这样的情况下&#xff0c;高速文件传输工具成为了一个热门话题。而aspera替代方案则…

React/Vue/Svelte 前端项目中开始使用TailwindCSS

背景 TailwindCSS 近年来在前端圈非常流行&#xff0c;它摆脱了原有的CSS限制&#xff0c;以灵活实用为卖点&#xff0c;用户通过各种class组合即可构建出漂亮的用户界面。对于初学者而言&#xff0c;可能需要一些上手成本&#xff0c;一旦掌握实用技巧后&#xff0c;Tailwind…

JetBrains Rider for Mac/win中文版- 跨平台.NET 开发的终极选择!

在.NET开发世界中&#xff0c;JetBrains Rider凭借卓越的性能和丰富的功能成为了开发者的首选。JetBrains Rider是一款跨平台.NET集成开发环境&#xff08;IDE&#xff09;&#xff0c;可在Windows和macOS上无缝运行&#xff0c;为.NET开发提供了卓越的工作体验。 JetBrains R…

C++新经典模板与泛型编程:用成员函数重载实现std::is_convertible

用成员函数重载实现is_convertible C标准库中提供的可变参类模板std::is_convertible&#xff0c;这个类模板的主要能力是判断能否从某个类型隐式地转换到另一个类型&#xff0c;返回的是一个布尔值true或false。例如&#xff0c;一般的从int转换成float或从float转换成int&am…

相控阵天线(十四):常规大阵列天线分布(椭圆阵列、三角阵列、矩形拼接阵列、栅格拼接阵列)

目录 简介椭圆阵列三角阵列子阵拼接的矩形阵列子阵拼接的圆形阵列圆形子阵拼接阵列子阵栅格拼接阵列 简介 前面的博客已经介绍过常见的平面阵有一些基本类型&#xff0c;本篇博客介绍一些实际工程中可能出现的阵列&#xff0c;包括椭圆阵列、子阵通过矩形拼接形成的矩形大阵列…

题目:分糖果(蓝桥OJ 2928)

题目描述&#xff1a; 解题思路&#xff1a; 本题采用贪心思想 图解 题解&#xff1a; #include<bits/stdc.h> using namespace std;const int N 1e6 9; char s[N];//写字符串数组的一种方法,像数组一样***int main() {int n, x;cin >> n >> x;for(int …

有哪些已经上线的vue商城项目?

前言 下面是一些商城的项目&#xff0c;需要练手的同学可以挑选一些来练&#xff0c;废话少说&#xff0c;让我们直接开始正题~~ 1、newbee-mall-vue3-app 是一个基于 Vue 3 和 TypeScript 的电商前端项目&#xff0c;它是 newbee-mall 项目的升级版。该项目包含了商品列表、…

EXP-00056: 遇到 ORACLE 错误 12154 ORA-12154: TNS: 无法解析指定的连接标识符

exp oas/oasoas filed:\daochu.dmp owner(s) 导出特定用户 //exp 用户名/密码数据库 filed:\daochu.dmp owner(用户名) 1.重启oracle监听 cmd 中输入 services.msc 找到服务&#xff1a;OracleOraDb10g_home1TNSListener 与 OracleServiceORCL。 把两个服务启动. 若未解决…

CRM系统选择技巧,什么样的CRM系统好用?

SaaS行业发展迅速&#xff0c;更多的企业逐渐选择CRM管理系统。打开搜索引擎&#xff0c;有非常多的结果。怎样在数十万个搜索结果中选择适合您的CRM系统&#xff1f;下面我们将聊聊&#xff0c;怎样选择CRM系统。 第一步&#xff1a;明确自身需求 重要性&#xff1a;每家企业…

机器学习与低代码开发:创新驱动的双剑合璧

引言 随着科技的日新月异&#xff0c;机器学习和低代码开发已经成为引领技术行业变革的两大重要趋势。机器学习通过模拟人类的学习方式&#xff0c;让计算机具备了自我学习和预测的能力&#xff0c;打破了传统计算机程序的局限性。而低代码开发则以简化软件开发过程为目标&…

leetcode 1466

leetcode 1466 如图 node 4 -> node 0 -> node 1 因为节点数是n, 边长数量是n-1。所以如果是从0出发的路线&#xff0c;都需要修改&#xff0c;反之&#xff0c;如果是通向0的节点&#xff0c;例如节点4&#xff0c;则把节点4当作父节点的节点&#xff0c;之间的路线的方…

土壤水分传感器土壤体积含水率含量监测仪器

产品概述 外型小巧轻便&#xff0c;便于携带和连接。 土壤水分传感器由电源模块、变送模块、漂零及温度补偿模块、数据处理模块等组成。传感器内置信号采样及放大、漂零及温度补偿功能&#xff0c;用户接口简洁、方便。 功能特点 ◆本传感器体积小巧化设计&#xff0c;测量…

妙手ERP功能更新:TikTok支持打印10×10面单、Ozon支持设置最低售价、超过90天的Shopee订单买家信息不再显示......

为了给卖家朋友带来更好的使用体验&#xff0c;更高效地运营跨境店铺&#xff0c;妙手ERP在上周优化了以下多项功能。 01、产品模块优化 全平台 - 自定义平台SKU时&#xff0c;连接符支持为空或可输入其他符号&#xff08;不支持输入数字、emoji、文字&#xff09; Ozon - 支…

modbus转profinet网关解决plc插槽号不够用的情况

PLC作为常用的控制设备之一&#xff0c;其插槽号有时会限制外部设备的连接数量。然而&#xff0c;通过使用modbus转profinet网关&#xff0c;可以解决这一问题。这种设备能够将modbus协议转换为profinet协议&#xff0c;实现PLC与更多外部设备的连接。 modbus转profinet网关还具…

【ET8】1.ET8入门-运行指南

主要学习网址 论坛地址为&#xff1a;https://et-framework.cn Git地址为&#xff1a;GitHub - egametang/ET: Unity3D Client And C# Server Framework 官方QQ群 : 474643097 项目检出 检出项目切换到release8.0分支 GitHub地址&#xff1a;GitHub - egametang/ET: Unity…

大数据毕业设计之前端02:架构布局和aside的设计

前言 上一篇主要讲了我学习前端的一个经历&#xff0c;以及为什么选择BuildAdmin作为深入前端学习的原因.同事也大致聊了一下学习前端需要使用哪些技术栈。 本篇文章来拆解一下BuildAdmin的前端代码结构&#xff0c;和布局实现的细节。 前端代码结构 必须先了解项目的结构&…

无人机巡检中台揭秘,无人机管控平台助力巡查无人机巡检方案落地

随着无人机智能巡检的飞速发展&#xff0c;巡查无人机应用场景也日益多元&#xff0c;无人机巡检方案被频繁落地到工业生产及巡检巡逻业务中。而无人机管控平台应运而生&#xff0c;成为推动无人机智能巡检的关键工具。那我们一起来看一下无人机管控平台的作用&#xff1a; 一、…