百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

记一次redis内存碎片率高引发的思考

mhr18 2024-12-02 17:59 14 浏览 0 评论

摘要:

本文详细描述了由redis磁盘碎片率高告警引发的告警分析处理过程,并对此次告警从产生原因进行了详细分析,最终找到根因并制定解决方案恢复系统正常。

通过总结本次案例遇到的问题,归为其他应用系统故障排除提供参考,并思考总结了运维工作中需要改进的地方。

关键字:redis 内存 碎片率

1、 背景Situation

360评估系统是为员工提供全面评价的评估系统,通过邮件和短信的形式邀请被评估人的上级、同级、下级来进行评估。在评估的过程中,为防止中途意外退出,导致填写内容消失从而重新填写这个问题,评估所填写的内容会被临时缓存至中间件redis中。

之前360评估系统只把操作系统层面指标接入zabbix监控,随着监控指标的不断丰富,6月初已完成中间件redis监控的接入,采用给定模板的形式,相应的触发器及阈值暂未调整。

2、 事件描述及问题Task

2024年7月5日,收到zabbix监控告警,告警内容为redis内存碎片率过高,已持续超过15分钟;之后的时间内陆续收到相应的告警,碎片率的值逐渐飙升。

3、 分析与对策Action

3.1、故障定位及根因分析

3.1.1、什么是内存碎片

当程序需要申请一块连续的地址空间N个字节时,剩余的内存空间中没有大小为N字节的连续空间,那么这些剩余空间即是内存碎片。内存碎片类似食堂座位,假设一个食堂的座位总共有100个,现在已经坐了90个座,我们现需要3个连在一起的座,但发现没有了。

3.1.2、内存碎片形成的原因

Redis 全称是 Remote Dictionary Server, 是一种基于键值对(key-value)的NoSQL数据库,Redis的值可以是由string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合)等多种数据结构和算法组成。Redis会将所有数据都存放在内存中,所以它的读写性能非常惊人。

既然redis是纯内存读写,那么就不得不提到内存分配策略,内存分配一般是按照固定大小来分配内存,而不是完全按照应用程序申请的内存空间大小给程序分配。

Redis 默认使用 jemalloc 分配内存,也就是当申请的内存最接近某个固定值时,jemalloc 会给它分配相应的大小空间。这也就是碎片产生的原因,申请了20字节的空间,操作系统会分配32 字节的空间,这样就会产生12个字节的空间碎片。这种现象一般发生在Redis的写操作上。

Redis内部有自己的内存管理器,为了提高内存使用的效率,来对内存的申请和释放进行管理。删除的时候,并没有把内存直接释放,交还给操作系统,而是交给了Redis内部有内存管理器。申请内存的时候,也是先看自己的内存管理器中是否有足够的内存可用。这种机制,提高了内存的使用率,但是会使Redis中有部分自己没在用,却不释放的内存。这种现象一般发生在redis删除操作上

此外键值进行修改时,可能会变大也会变小,相应的就会占用额外空间或者释放不用的空间也是产生碎片的原因之一。

3.1.3、内存碎片计算及意义

内存碎片是通过以下的公式计算出来的

Used Memory Rss :向操作系统申请的内存大小。

Used Memory :由Redis分配器分配的内存总量,包含了redis进程内部的开销和数据占用的内存(Redis实例中所有key及其value占用的内存大小)。

mem_fragmentation_ratio的不同值,说明不同的情况。

大于1:说明内存有碎片,一般在1到1.5之间是正常的。

大于1.5:说明内存碎片率比较大,需要考虑是否要进行内存碎片清理,要引起重视。

小于1:说明已经开始使用交换内存,也就是使用硬盘了,正常的内存不够用了,需要考虑是否要进行内存的扩容。

3.1.4、故障告警定位

通过以上碎片产生的原因分析,无非就是redis的增、删、改三个操作。由于该redis是用于缓存用户填写的问卷信息内容,结合碎片产生的三种原因,初步断定为先插入数据然后删除导致。之后从业务得到确认6月4日,进行了一次活动发起,集中对人员评估;通过redis客户端进入数据库执行info命令观察redis中keys变化,发现一直在减少,结合应用中在新增key时,设置了一个24小时过期删除策略,导致大量的key值删除。所以确认本次碎片率高告警为key值删除导致。

3.2、故障复现

准备一个新的测试redis库,执行flushall初始化数据库,清空所以key,之后查看内存碎片率为16.27。


测试数据准备,插入2万个string类型key,查看内存碎片率为3.46。由于新插入数据把原有的内存碎片占用,所以导致内存碎片率降低。

删除50%的测试数据,内存碎片率为4.69.

删除90%的测试数据,内存碎片率为9.4

使用redis自带命令测试系统延时

3.3、故障解决方案

当评估活动完成,重启Redis服务,Redis会将没用的内存归还给操作系统,碎片率会降下来。

4、 处理结果Result

本次告警是由于对内存碎片理解不深刻和告警触发条件不全面引起,所以针对于本次告警,修改redis配置,开启线上自动碎片清理,同时设置触发条件为碎片的字节数达到200m时开始清理。不过自动清理会造成性能的开销,所以需要设置active-defrag-cycle-max 50,表示自动清理过程所用 CPU 时间的比例不高于 50%,一旦超过,就停止清理,从而避免在清理时,大量的内存拷贝阻塞 Redis,导致响应延迟升高。

5、 建议与讨论Review

建议与讨论点一:监控告警配置与修改

目前接入zabbix监控的告警都是以模板为主,模板中的监控项及告警阈值体现的是一个大多数状态,我们需要根据各自系统自身情况,完成告警监控的丰富及告警阈值的优化。

针对本次redis告警虽然是内存碎片率高,但是实际数据占用的内存并不高,redis实际使用内存不到系统的10%,通过延迟测试证明内存碎片率高对其本身性能并没有影响;但是有一种情况需要注意,即redis实际使用内存较高,同时内存碎片率也高,该现象说明系统内存紧张,这时进行磁盘碎片整理是缓解内存紧张的一个办法。

监控告警配置与修改建议如下:

1、修改内存碎片率告警等级,改为通知即可(单独出现该告警时,了解情况即可,无需相应的操作)。

2、对于低于4.0版本redis,新增告警触发器,同时满足内存碎片率高和使用内存接近最大可使用内存两个条件,报警内存不足。

建议与讨论点二:redis配置修改

由于redis为纯内存读写,会不断使用系统内存,为了考虑系统稳定,需要限制redis的内存使用,此外redis4.0以上可以使用新增指令来手动回收内存碎片,可释放更多内存空间。

redis配置修改建议如下:

1、通过修改配置文件或者执行命令“set maxmemory”来限制redis最大内存的使用。

2、对于高于4.0版本redis,开启内存碎片自动清理。

config set activedefrag yes 自动碎片整理开启(默认设置内存碎片率大于10%且内存碎片大小超过100mb开始回收).

碎片大小可通过 active-defrag-ignore-bytes 200mb 调整

碎片率可通过 active-defrag-threshold-lower 20 调整

自动内存回收会使Redis集群的响应变高,因为内存碎片整理是在主线程中执行的,内存碎片整理操作会 scan (通过迭代进行)整个 redis 节点,并进行内存复制、转移等操作,因为 redis 是单线程的,所以会导致 redis 性能下降(通过调整相关配置可以控制内存整理对 redis 集群的影响)。

active-defrag-cycle-min和active-defrag-cycle-max这两个参数是占用主线程资源比率的上下限,如果想保证内存碎片整理功能不过度影响 redis 集群性能,则需要仔细斟酌着两个参数的配置,当资源占用越多时,内存碎片整理力度越大,时间越短,当然对redis性能的影响也更大。

相关推荐

如何检查 Linux 服务器是物理服务器还是虚拟服务器?

在企业级运维、故障排查和性能调优过程中,准确了解服务器的运行环境至关重要。无论是物理机还是虚拟机,都存在各自的优势与限制。在很多场景下,尤其是当你继承一台服务器而不清楚底层硬件细节时,如何快速辨识它是...

第四节 Windows 系统 Docker 安装全指南

一、Docker在Windows上的运行原理(一)架构限制说明Docker本质上依赖Linux内核特性(如Namespaces、Cgroups等),因此在Windows系统上无法直...

C++ std:shared_ptr自定义allocator引入内存池

当C++项目里做了大量的动态内存分配与释放,可能会导致内存碎片,使系统性能降低。当动态内存分配的开销变得不容忽视时,一种解决办法是一次从操作系统分配一块大的静态内存作为内存池进行手动管理,堆对象内存分...

Activiti 8.0.0 发布,业务流程管理与工作流系统

Activiti8.0.0现已发布。Activiti是一个业务流程管理(BPM)和工作流系统,适用于开发人员和系统管理员。其核心是超快速、稳定的BPMN2流程引擎。Activiti可以...

MyBatis动态SQL的5种高级玩法,90%的人只用过3种

MyBatis动态SQL在日常开发中频繁使用,但大多数开发者仅掌握基础标签。本文将介绍五种高阶技巧,助你解锁更灵活的SQL控制能力。一、智能修剪(Trim标签)应用场景:动态处理字段更新,替代<...

Springboot数据访问(整合Mybatis Plus)

Springboot整合MybatisPlus1、创建数据表2、引入maven依赖mybatis-plus-boot-starter主要引入这个依赖,其他相关的依赖在这里就不写了。3、项目结构目录h...

盘点金州勇士在奥克兰13年的13大球星 满满的全是...

见证了两个月前勇士与猛龙那个史诗般的系列赛后,甲骨文球馆正式成为了历史。那个大大的红色标志被一个字母一个字母地移除,在周四,一切都成为了过去式。然而这座,别名为“Roaracle”(译注:Roar怒吼...

Mybatis入门看这一篇就够了(mybatis快速入门)

什么是MyBatisMyBatis本是apache的一个开源项目iBatis,2010年这个项目由apachesoftwarefoundation迁移到了googlecode,并且改名为M...

Springboot数据访问(整合druid数据源)

Springboot整合druid数据源基本概念SpringBoot默认的数据源是:2.0之前:org.apache.tomcat.jdbc.pool.DataSource2.0及之后:com.z...

Linux 中的 &quot;/etc/profile.d&quot; 目录有什么作用 ?

什么是/etc/profile.d/目录?/etc/profile.d/目录是Linux系统不可或缺的一部分保留配置脚本。它与/etc/profile文件相关联,这是一个启动脚本,该脚...

企业数据库安全管理规范(企业数据库安全管理规范最新版)

1.目的为规范数据库系统安全使用活动,降低因使用不当而带来的安全风险,保障数据库系统及相关应用系统的安全,特制定本数据库安全管理规范。2.适用范围本规范中所定义的数据管理内容,特指存放在信息系统数据库...

Oracle 伪列!这些隐藏用法你都知道吗?

在Oracle数据库中,有几位特殊的“成员”——伪列,它们虽然不是表中真实存在的物理列,但却能在数据查询、处理过程中发挥出意想不到的强大作用。今天给大家分享Oracle伪列的使用技巧,无论...

Oracle 高效处理数据的隐藏神器:临时表妙用

各位数据库搬砖人,在Oracle的代码世界里闯荡,处理复杂业务时,是不是总被数据“搅得头大”?今天给大家安利一个超实用的隐藏神器——临时表!当你需要临时存储中间计算结果,又不想污染正式数据表...

Oracle 数据库查询:多表查询(oracle多表关联查询)

一、多表查询基础1.JOIN操作-INNERJOIN:返回两个表中满足连接条件的匹配行,不保留未匹配数据。SELECTa.emp_id,b.dept_nameFROMempl...

一文掌握怎么利用Shell+Python实现多数据源的异地备份程序

简介:在信息化时代,数据安全和业务连续性已成为企业和个人用户关注的焦点。无论是网站数据、数据库、日志文件,还是用户上传的文档、图片等,数据一旦丢失,损失难以估量。尤其是当数据分布在多个不同的目录、服务...

取消回复欢迎 发表评论: