Redis性能大挑战:深入剖析缓存抖动现象及有效应对的战术指南

        在实际应用中,你是否遇到过这样的情况,本来Redis运行的好好的,响应也挺正常,但突然就变慢了,响应时间增加了,这不仅会影响用户体验,还会牵连其他系统。

        那如何排查Redis变慢的情况呢?首先有个问题需要确定,就是确定Redis是否真的变慢了。

Redis基线性能

        要判断Redis是否变慢了,一个最直接的方法就是查看Redis的响应时间。

        大部分情况下,Redis的延迟很低,但是在某些情况下,Redis会出现很高的延迟,可能会达到几秒甚至更长,不过持续的时间又不长,这到底是怎么情况呢?如果出现了响应延迟到秒级别就可以确定Redis变慢了。

        首先需要先确定Redis的延迟绝对值,但是在不同运行环境下,Redis的绝对性能是不同的。所以就需要当前环境的基线性能,所谓基线性能,就是一个系统在低压力、无干扰下的基本性能,这个性能只由当前软硬件环境配置决定。

        基线性能可以通过Redis提供的命令来确定,具体为在redis-cli中添加--intrinsic-latency选项,可以用来检测和统计Redis在运行期间内的最大延迟,这就可以作为基线性能。

redis-cli -h localhost --intrinsic-latency 120
Max latency so far: 1 microseconds.
Max latency so far: 29 microseconds.
Max latency so far: 31 microseconds.
Max latency so far: 34 microseconds.
Max latency so far: 53 microseconds.
Max latency so far: 68 microseconds.
Max latency so far: 103 microseconds.
Max latency so far: 106 microseconds.
Max latency so far: 142 microseconds.
Max latency so far: 158 microseconds.
Max latency so far: 164 microseconds.
Max latency so far: 273 microseconds.
Max latency so far: 296 microseconds.
Max latency so far: 673 microseconds.
Max latency so far: 946 microseconds.
Max latency so far: 2138 microseconds.
Max latency so far: 2234 microseconds.
Max latency so far: 16164 microseconds.

2383205581 total runs (avg latency: 0.0504 microseconds / 50.35 nanoseconds per run).
Worst run took 321018x longer than the average latency.

        在自己的电脑上运行命令后,会打印120秒内检测到的最大延迟,可以看到这里的最大延迟为16164微妙,16ms左右。一般情况下,检测120s的时长已经够了。

        一般来说,运行时响应时间和基线性能做对比,如果响应时间达到了基线性能的2倍以上,就可以认定Redis变慢了。

Redis变慢的原因

        一旦发现变慢了,接下来就要查找原因解决这个问题了。这个过程要基于Redis本身的工作原理,并结合和它交互的操作系统、存储以及网络等外部系统的关键机制,在借助一些辅助工具来定位问题,并指定行之有效的解决方案。

        Redis变慢的原因有几下几点,如图所示:Redis变慢的原因

        慢查询指令

        慢查询命令,指在Redis中执行速度慢的命令,这会导致Redis延迟增加。Redis提供的命令操作很多,并不是所有命令都慢,这和命令操作的复杂度有关,所以我们必须知道不同命令的复杂度。

        比如,操作的value为String类型时,由于操作的事hash表,这个操作的复杂度是固定的,都是O(1),除非出现了hash碰撞严重。但操作的数据类型为集合时,如果集合中包含大量的元素,那这个操作复杂度是比较高的,会比较耗时。

        Redis官网提供了各个命令的复杂度:Commands | Redisicon-default.png?t=N7T8https://redis.io/commands/        如果有复杂的操作,就要考虑是否需要用简单的命令来替换。如果使用keys命令,查询大量的key,也会导致慢查询,因为需要扫描所有的键值对,所以生产环境要禁用这样的命令。

        删除key操作

        如果Redis中key过期了是会被自动删除的,这也是Redis的回收机制,Redis 的 key可以设置过期时间,默认情况下,每100ms就会扫描一次,删除过期的key,具体如下:

  • 采样ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP个数的key,并将其中过期的key全部删除;
  • 如果超过25%的key过期了,则重复删除过程,直到过期key的比例降至25%以下。

        如果触发了第二条规则,Redis就会一直删除以释放内存空间。注意,删除操作是阻塞的(Redis 4.0提供了异步机制减少阻塞)。所以一旦触发了就会一直删除key,这样一来,就没办法给客户端提供服务了。

        磁盘I/O:AOF

        为了保证数据的可靠性,Redis提供了AOF和RDB两种机制(想具体了解请查看:Redis持久化(AOF、RDB)用到的写时复制到底是什么-CSDN博客)。其中AOF提供了三种写回策略:always、everysec、no,这三种写回策略依赖文件系统来完成,也就是write和fsync。

        write把日志写到内核的缓冲区,就可以返回了,并不需要等待日志实际写回磁盘;而fsync需要把日志记录写回到磁盘才能返回,时间较长。

        当写回策略配置为everysec和always时,Redis需要调用fsync把日志写回磁盘。但是这两种写回策略的具体情况不一样。但不管怎么说,都会涉及到写回磁盘,而且fsync通常比较耗时,如果Redis主线程执行写回,就会造成阻塞。

        另外AOF日志重写时,也容易阻塞主线程,所以Redis使用了子线程来完成该操作。但是AOF重写会对磁盘又大量的IO操作,同时fsync又需要等到数据写到磁盘才能返回,所以,当AOF重写的压力比较大时,就会导致fsync阻塞,虽然fsync由后台子线程完成,但是主线程会监测fsync的执行进度。

        当主线程使用子线程执行了一次fsync,需要再次把接收的数据写回磁盘,如果主线程发现上一次的fsync还没有执行完,那么它就会阻塞。所以,如果后台线程执行fsync频繁阻塞的话,主线程也会阻塞,导致Redis性能变慢。

        内存大页

        内存大页机制也会影响Redis性能。Linux内核从2.6.38开始支持内存大页,支持2MB大小的内存页分配,而常规的也大小是4KB。你可能会说,Redis是内存数据库,内存大页对Redis不是有好处的吗,减少了内存的分配,但是任何事都有两面性,这时一个权衡的过程。

        Redis为了提高可靠性,提供了持久化的机制。这个过程需要额外的线程来执行,所以不会阻塞主线程为客户端提供服务。如果在持久化的过程中,客户端修改了数据,Redis会才用写时复制(Copy On Write)机制,数据一旦修改了不会直接修改内存中的数据,而是复制一份,然后再进行修改。

        如果采用了内存大页,那Redis就需要拷贝该大页。如果关闭了内存大页,那需要拷贝的页数据只有4kb,可见内存大页会复制大量数据。

        所以正常情况下,关闭内存大页就可以了。

        swap操作

        操作系统swap是将内存数据在内存和磁盘来回换入核换出的机制,涉及到磁盘的读写。所以一旦涉及到了swap,其性能都会收到磁盘性能的影响。

        Redis是内存数据库,内存使用量大,如果用Redis保存海量数据,而且没有控制好内存使用量,就可能会触发swap机制,从而影响性能。一旦触发swap机制,Redis需要操作磁盘才能完成,这回极大的降低Redis的性能。

        关于海量数据的处理请参考:面对海量数据Redis如何应对-CSDN博客

        Redis对于swap的排查有现成的命令,具体这里不做详细介绍了。

        内存碎片

        内存碎片很好理解,明明有内存空间,但是申请时就是无法分配需要的内存空间,这对于使用内存的Redis来说无疑影响巨大。

        内存碎片的原因

  1. 内存不是按需分配的,操作系统为了减少内存的分配次数,每次都是按照固定大小进行内存分配的,例如8字节、16字节、32字节等,比如申请了20字节的内存,但是实际上会分配32字节,此时如果在写入5字节数据,就不用再申请内存了,减少了内存申请的次数。
  2. Redis键值对大小不一和删除操作的影响,内存分配器只能按照固定大小分配内存。所以,分配的内存空间一般都会比申请的空间大一些,不会完全一直,这本身就会造成一定碎片,降低内存空存储效率。键值对会被修改或删除,这会导致空间的扩容和释放。一方面,如果修改后的键值对变大或变小了,就需要占用额外的空间或释放不用的空间。另一方面,删除的键值对就不在需要内存空间了,此时会把空间释放出来,变成空闲空间。

        如何判断内存碎片

        Redis是内存数据库,内存利用率的高低直接关系到Redis运行效率的高低。为了让用户能监控到实时的内存使用情况,Redis自身提供了info命令,可以用来查询内存使用的详细信息

info memory
# Memory
used_memory:1143520
used_memory_human:1.09M
used_memory_rss:1114112
used_memory_rss_human:1.06M
used_memory_peak:1144672
used_memory_peak_human:1.09M
used_memory_peak_perc:99.90%
used_memory_overhead:1096754
used_memory_startup:1079248
used_memory_dataset:46766
used_memory_dataset_perc:72.76%
allocator_allocated:1098416
allocator_active:1076224
allocator_resident:1076224
total_system_memory:8589934592
total_system_memory_human:8.00G
used_memory_lua:37888
used_memory_lua_human:37.00K
used_memory_scripts:0
used_memory_scripts_human:0B
number_of_cached_scripts:0
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
allocator_frag_ratio:1.1
allocator_frag_bytes:18446744073709529424
allocator_rss_ratio:1.00
allocator_rss_bytes:0
rss_overhead_ratio:1.04
rss_overhead_bytes:37888
mem_fragmentation_ratio:1.01
mem_fragmentation_bytes:15696
mem_not_counted_for_evict:0
mem_replication_backlog:0
mem_clients_slaves:0
mem_clients_normal:16986
mem_aof_buffer:0
mem_allocator:libc
active_defrag_running:0
lazyfree_pending_objects:0

        mem_fragmentation_ratio指标表示内存碎片化率,该值大于1但小于1.5时,这种情况是正常的,因为内存碎片是无法避免的。如果该值大于1.5,就表名内存碎片化率比较严重了,超过了50%,这时需要采取措施来处理内存碎片化。

        Redis从4.0版本后提供了专门清理内存碎片化的参数,通过该参数来设置内存碎片化的清理的开始和结束时机,以及占用CPU比例,从而减少碎片清理对Redis本身请求处理的性能影响。

config set activedefrag yes

        这个命令只是启动了自动清理功能,但具体什么时候清理,会受下面两个参数的控制。这两个参数分别设置了触发内存清理的一个条件,如果同时满足这两个条件,就开始清理,清理过程中,只要有一个条件不满足,就停止清理。

  • active-defrag-ignore-bytes 100mb:表示内存碎片的字节数达到100MB时,就开始清理。
  • active-defrag-threshold-lower 10:表示内存碎片空间占操作系统分配给Redis的总空间比例达到10%时,开始清理。

总结

        关于Redis变慢的问题排查就介绍到这里,不知道你有没有清晰的思路,欢迎关注并留言讨论。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

nginx配置 请求静态文件时带上额外的响应头信息

注意:这种方式添加的额外信息会出现在响应头中。 例如在location{}中,try_files之前添加如下信息: add_header X-Extra-Header "Value"; add_header X-Forwarded-For $proxy_add_x_forwarded_for; …

Gitlab-ci:从零开始的前端自动化部署

一.概念介绍 1.1 gitlab-ci && 自动化部署工具的运行机制 以gitlab-ci为例: (1) 通过在项目根目录下配置.gitlab-ci.yml文件,可以控制ci流程的不同阶段,例如install/检查/编译/部署服务器。gitlab平台会扫描.gitlab-ci.yml文件&…

【Python】Sigmoid和Hard Sigmoid激活函数对比总结及示例

Sigmoid和Hard Sigmoid是两种常用的激活函数,它们在神经网络中起到非线性变换的作用。以下是它们之间的对比和优缺点总结: Sigmoid激活函数: 优点: 输出范围是0到1之间,可以用于二分类问题。函数形状相对平滑&#…

【LeetCode】组合两个表(mysql)

题目 编写解决方案,报告 Person 表中每个人的姓、名、城市和州。如果 personId 的地址不在 Address 表中,则报告为 null 。 以 任意顺序 返回结果表。 结果格式如下所示。 答 select firstName ,lastName,city,state from Person left join Address …

使用pygame.draw绘制基本图形

import pygame# 初始化pygame pygame.init()# 创建显示窗口 screen pygame.display.set_mode((640, 480)) pygame.display.set_caption("绘制基本图形")# 定义颜色 BLACK (0, 0, 0) WHITE (255, 255, 255) RED (255, 0, 0) GREEN (0, 255, 0) BLUE (0, 0, 255)…

Mac安装nvm以及使用nvm安装node

1. 安装nvm命令 git clone https://gitee.com/mirrors/nvm.git ~/.nvm && cd ~/.nvm && git checkout git describe --abbrev0 --tags2. 配置环境变量 vi ~/.bash_profileexport NVM_DIR"$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] &&…

网络安全工具:通过监控分析日志数据保护企业网络

由于混合工作模式的兴起以及业务运营向云环境的迁移,企业网络变得更加分散和复杂,仅安装外围安全解决方案只会创建一个基本的防御层,系统、服务器和其他网络实体会生成记录所有网络活动的日志。集中式日志管理系统可以帮助管理员自动监控网络…

【教学类-45-06】正确 X-Y之间的三连加减题混合 (竖向排列)(44格:11题“++ ”11题“--”11题“ +-”11题“ -+” )

作品展示: 背景需求: 把以下四款3连题 混在一起,每种题目随机抽取11题,一共44格 出现问题: 1、- 、-里面有重复题 2、升序排列最好竖排展示 素材准备: ​ ​ 问题改正 1、单元格修改:确保竖列写入 …

【elastic search】JAVA操作elastic search

目录 1.环境准备 2.ES JAVA API 3.Spring Boot操作ES 1.环境准备 本文是作者ES系列的第三篇文章,关于ES的核心概念移步: https://bugman.blog.csdn.net/article/details/135342256?spm1001.2014.3001.5502 关于ES的下载安装教程以及基本使用&…

鸿蒙Harmony--状态管理器--@Prop详解

纵横千里独行客,何惧前路雨潇潇。夜半浊酒慰寂寞,天明走马入红尘。且将新火试新茶,诗酒趁年华。青春以末,壮志照旧,生活以悟,前路未明。时间善变,可执着翻不了篇。时光磨我少年心,却…

正则表达式、文件访问(Python实现)

一、主要目的: 1.了解正则表达式的基本概念和处理过程。 2.掌握使用正则表达式模块 Re 进行字符串处理的方法。 3.了解文件的基本概念和类型。 4.掌握在 Python 中访问文本文件的方法和步骤。 5.熟悉在 Python 中访问二进制文件的方法和步骤。 二、主要内容和结…

HelpLook VS Docusaurus:SaaS 知识库软件和 SSG 的对比

在选择文档工具时,需要考虑多个因素,如功能、易用性、成本等。Docusaurus是一个开源工具,它因其灵活性而受到文档团队的青睐,尤其是负责软件产品文档的团队。有些组织甚至可能要求使用开源软件,因此选择一个开源工具如…

读元宇宙改变一切笔记04_网络化

1. 思想实验 1.1. 如果森林中的一棵树倒下,但周围没有人听到,那它是否会发出声音? 1.1.1. “贝克莱的树” 1.2. 主观唯心主义哲学家乔治贝克莱(George Berkeley)提出的,他认为“存在就是被感知” 1.2.1. 如果有人或有其他事物…

CMake入门教程【高级篇】qmake转cmake

😈「CSDN主页」:传送门 😈「Bilibil首页」:传送门 😈「动动你的小手」:点赞👍收藏⭐️评论📝 文章目录 1. 概述2.qmake与cmake的差异3. qmake示例4.qmake转cmake示例5.MOC、UIC和RCC…

1991-2022年A股上市公司股价崩盘风险指标数据

1991-2022年A股上市公司股价崩盘风险指标数据 1、时间:1991-2022年 2、来源:整理自csmar 3、指标:证券代码、交易年度、NCSKEW(分市场等权平均法)、NCSKEW(分市场流通市值平均法)、NCSKEW(分市场总市值平均法); NCSKEW(综合市…

网络协议与攻击模拟_03实施ARP欺骗和攻击

一、ARP攻击 1、实验环境 kali Linux (安装arpspoof工具)被攻击主机 2、kali配置 kali Linux系统是基于debian Linux系统,采用deb包管理方式,可以使用apt源的方式进行直接从源的安装。 配置kali网络源 vim /etc/apt/sources…

本地远程实时获取无人机采集视频图像(天空端 + jetson nano + 检测分割 + 回传地面端显示)

1、无线图传设备介绍 2、jetson nano天空端数据采集检测保存 3、本地回传显示 1、无线图传设备介绍 由于本设计考虑将无人机得到检测结果实时回传给地面站显示,因此需要考虑一个远程无线通信设备进行传输。本设计采用思翼HM30图传设备。通过无线图传的wifi将天空端…

基于JavaWeb+BS架构+SpringBoot+Vue协同过滤算法的体育商品推荐系统的设计和实现

基于JavaWebBS架构SpringBootVue协同过滤算法的体育商品推荐系统的设计和实现 文末获取源码Lun文目录前言主要技术系统设计功能截图订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 文末获取源码 Lun文目录 1 绪 论 1 1.1项目背景 1 1.2研究意义 2 1.3设计目的 2 1.…

【动态规划】C++ 算法458:可怜的小猪

作者推荐 视频算法专题 涉及知识点 动态规划 数学 力扣458:可怜的小猪 有 buckets 桶液体,其中 正好有一桶 含有毒药,其余装的都是水。它们从外观看起来都一样。为了弄清楚哪只水桶含有毒药,你可以喂一些猪喝,通过观察猪是否…

ROS2——开发第一个节点

ROS2 的包必须在 src 文件夹下,使用下面的命令创建一个包,并设置相关的依赖 ros2 pkg create my_package --dependencies rclcpp std_msgs可以打开包内的 package.xml ,查看 depend 有哪些依赖 #include "rclcpp/rclcpp.hpp" int …