高并发内存占用持续下降_师兄,为什么删除数据后,Redis内存占用依然很高?...

前言

上周刚来了个应届小师弟,组长说让我带着,周二问了我这样一个问题:师兄啊,我用top命令看了下服务器的内存占用情况,发现Redis内存占用严重,于是我就删除了大部分不用的keys,为什么内存占用还是很严重,并没有释放呢?

嗯?为什么呢?今天就带着这个问题来介绍一下如何正确释放Redis的内存。

什么是内存碎片?

内存碎片这个概念应该不是第一听说了,熟悉JVM或者操作系统的应该都熟悉,以火车卖票为例,一个车厢128个车位,由于高峰期,只剩余两个位置了,但是此时三个人想要坐在一起,能够吹吹牛批,喝喝酒的,那么这三个人肯定不会买这节车厢的两个位置了,此时这两个位置可以称之为座位碎片 。

操作系统中对于内存分配也是一样的,比如应用需要申请一块连续N个字节的空间,虽然剩余内存总量大于N个字节,但是没有一块连续的内存空间是N个字节,那么剩余的空间就是内存碎片。如下图:

6a08c5d6244460b37181538ff4adb5bb.png

上图中的空闲3个字节和空闲2个字节都是内存碎片。

那么什么原因会造成内存碎片呢?这个其实大致分为两个原因,一个是操作系统的内存分配策略,一个是Redis自身原因,下面就这两个原因详细分析。

内存分配器的分配策略

内存分配器的分配策略一般是按照固定大小来分配内存,而不是按照应用程序申请的内存空间按需分配。比如8字节、16字节、32字节......

Redis提供了多种的内存分配策略,比如libcjemalloctcmalloc,默认使用jemalloc

jemalloc这种分配策略,是按照固定的空间分配,比如8字节、32字节....2KB、4KB等。当应用程序申请的内存接近某个固定值的时候,jemalloc则会分配固定的大小。比如申请了6字节,则会分配8字节的空间。

这种分配的方式的好处很明显,则会减少内存分配的次数,比如申请了20字节的内存,实际分配的是32字节的内存空间,当应用再写入10字节的数据时,则不会再次分配,剩余的12字节足够用了。这样就避免了一次的内存分配。如下图:

1c0e46fb418007d3e387a6f5b0955419.png

但是坏处也很明显,申请的和分配的空间不一样,则剩余的空间很可能形成内存碎片,一旦内存碎片多了,内存利用率也会随之降低,这是很可怕的。

Redis自身的原因

Redis作为键值对存储的数据库,本身键值对的大小就是不确定的,正如上面的例子中,Redis申请了20字节的空间,但实际分配却是32字节,那么剩余的12字节则会被闲置成为内存碎片。如下图:

bf382c2dfe88f05584168645b4cda100.png

上图中剩余12个字节空间则是闲置的,很有可能成为内存碎片,因此键值对大小不同则会造成一定的内存碎片,这是第一个原因。

第二个原因其实理解起来很简单,键值对的修改或者删除肯定会造成空间的扩容或者释放;

一方面,如果修改后的键值对变大或者变小了,势必会将占用的空间扩大或者释放不用的空间,如下图:

6344602f873f08a6a2c510da7f2131a8.png

上图中键值对修改后变小了,从原来的10个字节变成了7个字节,从而释放了3个字节,此时剩余了5个字节的空闲空间。

另一方面,如果键值对删除了,则会释放掉占用的空间,形成空闲空间。

如何判断存在内存碎片?

这个对于运维人员来说很重要,一旦出现Redis运行缓慢或者阻塞了,一定需要先判断内存的占用情况,而不是说胡乱的重启Redis。

Redis自身提供了INFO命令,可以用来查询内存的使用情况,命令如下:


INFO memory
# Memory
used_memory:1073741736
used_memory_human:1024.00M
used_memory_rss:1997159792
used_memory_rss_human:1.86G

mem_fragmentation_ratio:1.86

上面的各种属性含义如下:

823c7674b6c8a2193fdf2bb9c3958f3c.png

mem_fragmentation_ratio这个指标很清楚的展示了当前内存的碎片率,比如Redis申请了1000字节,但是操作系统实际分配的内存1800个字节,则mem_fragmentation_ratio=1800/1000=1.8

从上文也知道了,由于内存分配器的局限性,实际分配的内存绝大部分都是大于实际申请的内存,则如何通过mem_fragmentation_ratio这个值来衡量呢?这个值的范围在多少是正常的呢?

作者这里参照了许多开发人员的建议,列出了以下经验阀值:

  1. >1&&<1.5:在这个范围内是合理的,毕竟大部分情况下操作系统分配的内存总是总是大于实际申请的空间。
  2. >1.5:这表明内存碎片率已经超过50%,此时需要采取一些措施来降低碎片率了。
  3. <1:what?表明实际分配的内存小于申请的内存了,很显然内存不足了,这样会导致部分数据写入到Swap中,之后Redis访问Swap中的数据时,延迟会变大,性能会降低。

如何清理内存碎片?

既然存在内存碎片,那么的一定有方法清除内存碎片,最简单的方法则是重启Redis

但是这也存在一些风险,如下;

  1. 如果Redis未持久化,则数据会丢失(忽略从后端恢复)
  2. 即使持久化了,但是恢复数据时长不定,这个要根据AOF和RDB文件大小决定,在恢复阶段则无法提供服务。

好在Redis 4.0-RC3版本之后,Redis自身提供了一种清除内存碎片的方法

清除的原理很简单,通过复制拷贝将不连续的存放的数据搬到一起形成一块连续的内存空间,如下图:

f3d050a11e31b23345f0219e5e4cfeeb.png

如上图,清除之前AB不是连续的,中间隔着两个字节空闲1,但是在执行清除内存碎片操作之后,Redis拷贝了B空闲1,释放掉之前B的空间,此时空闲1空闲2则变成了连续的空闲空间了。

那么问题来了,这种方式固然好,但是对于单线程的Redis来说,通过这种拷贝复制的方式显然是一种耗时的操作,性能大大降低,那么有什么好的方法呢?

Redis提供了参数配置,可以控制清除内存碎片的时机,命令如下:

config set activedefrag yes

以上命令启动自动清理,但是具体什么时候清理,还要受以下两个参数的影响:

  1. active-defrag-ignore-bytes 400mb:如果内存碎片达到了400mb,开始清理(自定义)
  2. active-defrag-threshold-lower 20:内存碎片空间占操作系统分配给 Redis 的总空间比例达到20%时,开始清理(自定义)

以上两个参数只有全部满足才会开始清理

除了以上触发清理内存碎片的参数,Redis还提供了两个参数来保证在清理过程中不影响处理正常的请求,如下:

  1. active-defrag-cycle-min 25:表示自动清理过程所用 CPU 时间的比例不低于 25%,保证清理能正常开展
  2. active-defrag-cycle-max 75:表示自动清理过程所用 CPU 时间的比例不高于 75%,一旦超过,就停止清理,从而避免在清理时,大量的内存拷贝阻塞 Redis,导致响应延迟升高。

以上两个参数控制了清理过程中的CPU时间占比,保证了正常处理请求不受影响

总结

本文以师弟的一个疑问开头介绍了删除数据导致内存占用还是很高的原因是存在内存碎片,导致内存碎片大致分为两个原因,如下:

  1. 内存分配策略局限性,一般都会分配固定的空间大小,导致实际分配的内存空间大于实际申请的,从而多出了许多不连续的空闲内存块。
  2. 键值对的修改、删除导致了内存的扩容或者释放,导致多余的不连续的空闲内存块。

介绍了如何通过INFO memory命令查看内存的碎片率,通过mem_fragmentation_ratio的经验阀值来判断异常。

介绍了Redis清理内存碎片的方式以、自动清理的两个触发条件、保证正常处理请求的两个控制CPU时间的参数。

另外,作者已经完成了两个专栏的文章Mybatis进阶、Spring Boot 进阶 ,已经将专栏文章整理成书,有需要的公众号回复关键词Mybatis 进阶Spring Boot 进阶免费获取。

c7971a3ce367789debda4d6ea42c2745.png
fde134451c082771570f945f67bd5e72.png

往期推荐

给你一个亿的keys,Redis如何统计?

《Spring Boot 进阶》肝了五万多字的专栏文章,整理成册,免费获取!!!

程序员需知的 58 个网站

宕机了,Redis数据丢了怎么办?

单线程的Redis有哪些 "慢" 动作?

头秃系列,二十三张图带你从源码分析Spring Boot 启动流程~

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

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

相关文章

发现保存GIF格式后相素发生变化咋办

数学公式编辑器MathType主要的作用就是编辑公式用的&#xff0c;一些用户朋友编辑完公式希望把公式保存为“高分辨率”的GIF格式&#xff0c;但是在图片查看器中进行浏览查看时发现GIF的分辨率发生了变化&#xff0c;对于这种情况该如何处理呢&#xff1f;下面我们就针对这个问…

湖北计算机技能高考专科学校排名,湖北2021年技能高考专科录取分数线

https://forms.ebdan.net/ls/wg2YPHOQ点击查看全部院校武汉船舶职业技术学院&#xff1a;技能高考(机械类)507技能高考(电气电子类)437技能高考(计算机类)532技能高考(财经类)530技能高考(建筑设计类)319技能高考(旅游类)489技能高考(汽车维修类)466湖北科技职业学院&#xff1…

7月19日实习日志

今天是实习第十二天&#xff0c;时间过得很快一转眼实习一般都已经过去了&#xff0c;今天早上下了大雨&#xff0c;到单位的时候差一点迟到。 今天难道单位公司的同事就带领着我给公司的防火请升级&#xff0c;防火墙可以是一套硬件或软件&#xff0c;它在网络和互联网之间形成…

计算机考研985院校不歧视,考研最不歧视的985大学有哪些

考研最不歧视的大学有很多&#xff0c;其中985院校有哈尔滨工业大学、对外经济贸易大学、中南大学、河南大学和华东师范大学等。哪些985大学不歧视考研考生1、哈尔滨工业大学面试除了自我介绍&#xff0c;其他都不透露自己的信息&#xff0c;面试老师也都不知道&#xff0c;都是…

Python | Tkinter中的文本区域和按钮

Library: 图书馆&#xff1a; TkinterTkinter (Tkinter) Tkinter(Tk interface) is a Standard python library that is used to create easy, fast, and simple GUI applications. Tkinter(Tk接口)是一个标准的python库&#xff0c;用于创建简单&#xff0c;快速和简单的GUI应…

十六进制转八进制c++代码_如何将十六进制代码上传到微控制器?

十六进制转八进制c代码Read: 8051 Microcontroller programming using Keil Uvision IDE 阅读&#xff1a; 使用Keil Uvision IDE进行8051单片机编程 将HEX文件上传到微控制器 (Uploading a HEX file to Microcontroller) Once you have developed the hex code for the progr…

java工程师占比_Java工资怎么样?哪个地方Java工作机会最多?

随着IT产业的发展&#xff0c;JAVA语言因其独有的特点&#xff0c;使其在各项服务器中应用程序的开发所占有一定的优势&#xff0c;随着JSP技术的发展&#xff0c;使Java语言的网络应用更为实际化、更高效快捷&#xff0c;成为IT产业常用的技术。 越来越多的企业&#xff0c;因…

Nginx主配置文件nginx.conf中文详解

第1章 nginx配置解释图解第2章 Nginx核心配置文件nginx.conf史上最细中文详解2.1 定义Nginx运行的用户和用户组2.2 nginxworker进程数&#xff0c;即处理请求的进程&#xff08;熟称负责接客的服务员&#xff09;2.3 cpu亲和力配置&#xff0c;让不同的进程使用不同的cpu2.4 全…

0到100速度测试软件,【图】到底如何完成 揭晓0-100公里/小时测试_汽车江湖

经常浏览汽车网站的朋友应该对0-100公里/小时加速测试并不会感到陌生&#xff0c;几乎所有深度测试车型都会经历的考验&#xff0c;而在各个汽车官网上通常也会将这一数值标出。然而&#xff0c;这个成绩到底是如何测出的&#xff0c;或许大多数人并不十分知晓&#xff0c;接下…

计算机毕业设计谢辞怎么写,毕业论文谢辞怎么写(通用8篇)

毕业论文谢辞怎么写(通用8篇)一段忙碌又充实的大学生活要即将结束&#xff0c;毕业前要通过最后的毕业论文&#xff0c;毕业论文是一种有准备、有计划、比较正规的、比较重要的检验大学学习成果的形式&#xff0c;那么你有了解过毕业论文吗&#xff1f;以下是小编为大家整理的毕…

J2EE基础之Web服务简介

J2EE基础之Web服务简介 1、什么是Web服务&#xff1f; 在人们的日常生活中&#xff0c;经常会查询网页上某城市的天气信息&#xff0c;这些信息都是动态的、实时的&#xff0c;它是专业的气象站提供的一种服务。例如&#xff0c;在网上购物时&#xff0c;通常采用网上支付的方式…

计算机安装重装出现错误,一键重装失败怎么办?电脑重装系统失败的原因和解决方法...

在电脑出现问题的时候&#xff0c;我们可以通过重装系统来解决电脑问题。但有的时候重装系统失败&#xff0c;无法进行安装&#xff0c;这可怎么办呢&#xff1f;下面就让小编为大家带来电脑重装系统失败的原因和解决方法。1、启用了防毒功能问&#xff1a;当重装系统时&#x…

System Center Technical Preview DPM(2016)对Exchange2016的灾难恢复

其实备份很简单&#xff0c;就是做好备份计划即可&#xff0c;但往往客户最担心的是备份的东西在真的灾难恢复时是否可以恢复出来可用&#xff0c;这才是考验备份软件的最关键时刻&#xff0c;因此象备份Exchange这样的应用时对于管理员来说除了会玩备份软件外还需要熟悉Exchan…

教你在Ubuntu上体验Mac风格

导读老实说&#xff0c;我是个狂热的 Ubuntu 迷&#xff0c;我喜欢 Ubuntu 默认的 Unity 主题样式外观。此外&#xff0c;还有很多关于 Ubuntu 14.04 的漂亮图标主题样式 可用来美化默认的外观。但正如我上面提到的仍有很多用户喜欢 Mac OS X 的主题样式&#xff0c;我希望这篇…

在Python中升级灰度图像

Upscaling of an image refers to enlarging the size of an image. 图像放大是指放大图像的大小。 In this program, we will be using two functions of OpenCV-python (cv2) module.. lets see their syntax and descriptions first 在此程序中&#xff0c;我们将使用Open…

安卓投屏软件_有哪些好用又免费的手机投屏到电脑的软件?

推荐一款免费、好用的投屏软件&#xff0c;叫做【快投屏】&#xff0c;支持多端无线一键投屏、远程投屏&#xff0c;不限制使用时间&#xff0c;不压缩投屏画质。快投屏 - 手机投屏到电视,电脑的无线投屏软件​支持以下几种投屏&#xff1a;手机投电视手机投电脑手机投手机电脑…

dnf韩服服务器维护中,DNF2019韩服4.30维护:这些职业被加强

DNF韩服4.30维护DNF2019韩服4.30更新内容 DNF95版本4.30韩服更新内容 DNF95版本职业平衡。相信大家都很想知道吧&#xff0c;一起来看看吧。地下城一直被称为鬼剑士的游戏&#xff0c;无论是在何地图&#xff0c;如果看不到鬼剑士的话那就是太阳打西边出来了&#xff0c;9成勇士…

java 实现 堆排序算法_C程序实现堆排序算法

java 实现 堆排序算法Heap Sort is a comparison-based sorting algorithm that makes use of a different data structure called Binary Heaps. Let us understand some important terms, 堆排序是一种基于比较的排序算法&#xff0c;该算法利用称为二进制堆的不同数据结构。…

b+树时间复杂度_数据结构:线性表,栈,队列,数组,字符串,树和二叉树,哈希表...

作者&#xff1a;张人大代码效率优化复杂度 -- 一个关于输入数据量n的函数时间复杂度 -- 昂贵与代码的结构设计有着紧密关系一个顺序结构的代码&#xff0c;时间复杂度是O(1), 即任务与算例个数 n 无关空间复杂度 -- 廉价与数据结构设计有关数据结构 -- 考虑如何去组织计算机中…

评价最高影片JAVAlibrary_视频 | 手游大神,动画导演,机圈新贵,极客怎么评价《愤怒的小鸟2》?...

谁能想到&#xff0c;迄今为止口碑最好的「游戏改编电影」竟然来自一个手机游戏IP&#xff1f;&#xff01;《愤怒的小鸟2》是有史以来评价最好的游戏改编电影。—— http://Screencrush.com《愤怒的小鸟2》凭什么能在打分平台上获得游戏改编电影最高分&#xff1f;—— http:/…