高并发内存占用持续下降_师兄,为什么删除数据后,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,一经查实,立即删除!

相关文章

如何打印出给定尺寸的方格_打印给定号码的表格| 8085微处理器

如何打印出给定尺寸的方格Problem statement: 问题陈述&#xff1a; Write an assembly language program in 8085 to print the table of input integer. 在8085中编写汇编语言程序以打印输入整数表。 Assumptions: Suppose the inputted number is at memory location 2050…

maka如何看html文件,自己在MAKA上做得H5,别人如何能看到收集的信息

1。登陆1。 ? ?登陆入口&#xff1a;点击首页右上角“登录”按钮进入登录界面&#xff1b;2。 ? ?登陆界面&#xff1a;输入有效注册的个人账号信息&#xff1a;邮箱、密码&#xff1b;您也可以选择QQ等第三方登录。3。 ? ?密码找回&#xff1a;进入账户登录界面&#xf…

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

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

3个阶段 项目征名_2020年即将上线的3个爆款,或许它们能改变现有的手游格局...

在近几年国内的手游市场中&#xff0c;基本都被《王者荣耀》和吃鸡类型的给垄断了&#xff0c;偶尔有个别爆款出现&#xff0c;也只是昙花一现&#xff0c;连半年时间都坚持不到&#xff0c;就比如去年的自走棋。不过在2020年&#xff0c;以王者和吃鸡为主的这种格局或许会被打…

python判断素数程序_使用面向对象方法检查素数的Python程序

python判断素数程序This program will check whether a given number is Prime or Not, in this program we will divide the number from 2 to square root of that number, if the number is divided by any number in b/w then the number will not be a prime number. 该程…

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

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

定位样式

Web页面中的特殊效果&#xff0c;如菜单效果&#xff0c;对话框效果都需要通过定位属性来实现。定位样式position属性可以控制元素的定位类型position属性值可以为sataic、fixed、absolute、relativeposition属性的语法结构- position:value;定位属性static默认值。没有定位&am…

c#异常处理_C#异常处理能力问题和解答 套装2

c#异常处理1) There are the following statements that are given below, which is correct about an exception in C#.NET? The exception occurs at the time of compilationThe exception occurs during program loadingThe exception occurs during JIT compilationThe …

考虑题4所示的日志记录_[南开大学]18秋学期(1703)《数据库基础与应用》在线作业...

18秋学期(1703)《数据库基础与应用》在线作业一、单选题&#xff1a;1.[单选题]在SQL语言中&#xff0c;模式对应于() (满分:)A. 视图和部分基本表B. 基本表C. 存储文件D. 物理磁盘正确答案:——B——2.[单选题]在数据库系统中&#xff0c;读脏数据是指一个事务读了另…

数字图像处理图像反转的实现_反转8位数字| 8085微处理器

数字图像处理图像反转的实现Problem statement: 问题陈述&#xff1a; To reverse 8 bits number using 8085 microprocessors. 使用8085微处理器反转8位数字。 Algorithm: 算法&#xff1a; Load the accumulator with the first data. 向累加器加载第一个数据。 Use RLC i…

计算机控制z反变换公式,第三章 计算机控制系统的数学描述(修正Z变换).ppt

第三章 计算机控制系统的数学描述(修正Z变换)* 3.4 修改Z变换 1&#xff0e;具有多采样频率系统 在某些控制系统中&#xff0c;存在着不同采样频率的采样开关&#xff0c;如图3.10所示。 图3.10 具有不同采样频率系统结构图 图3.10表示&#xff0c;该系统反馈回路的采样频率高一…

7月19日实习日志

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

g++默认参数_C ++默认参数| 查找输出程序| 套装2

g默认参数Program 1: 程序1&#xff1a; #include <iostream>using namespace std;int K 10;int fun(){return K;}int sum(int X, int Y fun()){return (X Y);}int main(){int A 0;A sum(5);cout << A << " ";K 20;A sum(5);cout <<…

python重载模块_Python 3.0中重载模块

在Python中&#xff0c;每一个以 .py结尾的Python文件都是一个模块。其他的文件可以通过导入一个模块来读取该模块的内容。导入从本质上来讲&#xff0c;就是载入另一个文件&#xff0c;并能够读取那个文件的内容。一个模块的内容通过这样的属性能够被外部世界使用。这种基于模…

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

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

如何使用Tornado实现WebSocket服务器?

什么是龙卷风&#xff1f; (What is Tornado?) Tornado is a python web framework and asynchronous networking library. It is scalable and non-blocking. It specializes in dealing with event-driven networking. As tornado supports concurrent connections, natural…

电子增稳云台_揭秘Dobby自拍无人机,电子增稳是黑科技?

揭秘Dobby自拍无人机&#xff0c;电子增稳是黑科技&#xff1f;2016年07月27日 10:47作者&#xff1a;广州分站文章出处&#xff1a;泡泡网原创分享最近零度智控的Dobby自拍无人机横空出世&#xff0c;主打「便携」「自拍」两大特色&#xff0c;一经众筹便得到了大量的关注&…

拖动效果

css部分&#xff1a; <style type"text/css">.page{text-align:left;}.dragDiv{   border:1px solid #ddd;   padding:10px;   width:300px;   height:150px;   margin:0 auto;   border-radius:4px;    box-shadow:0 1px 2px #fefefe;    pos…

计算机组成比作人的什么位置,理学第章计算机组成上.ppt

理学第章计算机组成上.ppt第2章 计算机组成原理 2.1 计算机系统组成简介 计算机系统由硬件和软件两大部分组成。若把一个计算机系统比作人的话&#xff0c;则硬件构成了计算机系统进行计算的躯干&#xff0c;软件构成了计算机系统进行计算的大脑。 1 输入部件 输入部件用于向计…

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应…