Redis数据已经删除了,为什么内存占用还是很高?

Redis数据已经删除了,为什么内存占用还是很高?

Redis做了数据删除操作,为什么使用top命令时,还是显示Redis占了很多内存?

没做相关功课的人觉得这个问题有问题,删了数据还说占着内存,面试官不是在误导我吗,事实并非如此!

这里先说答案 📝📝

🌐 实际上,这是因为,当数据删除后,Redis 释放的内存空间会由内存分配器管理,并不会立即返回给操作系统。所以,操作系统仍然会记录着给 Redis 分配了大量内存。

而 used_memory_rss 记录着在操作系统角度,Redis进程占用的物理总内存

这样看来文章好像讲完了,开头就知道答案,当然不是,内容多着呢~

文章将从下面这些点分析扩展你对于Redis内存方面的知识点,以及内存碎片和如何清理内存碎片。

在这里插入图片描述
Redis内存消耗组成
Redis内存消耗主要在于其主进程消耗和子进程消耗。而主进程消耗又主要包括自身内存、对象内存、缓冲区内存、内存碎片四个方面:

在这里插入图片描述
自身进程占用内存
Redis进程自身所占用的内存,这部分内存通常很小,一个空的Redis进程所消耗的内存几乎可以忽略不计

数据对象内存
对象占用的内存是Redis中占用内存最大的,这里存储这我们的键值对,我们知道不同的数据类型占用的内存空间大小也不同,特别是那种大key占用内存的情况就更惊人了。

缓冲区
Redis主要有三大缓冲区:客户端缓冲区、AOF缓冲区、复制缓存区

在这里插入图片描述
📔 客户端缓冲区: 为了解决客户端和服务端请求和处理速度不匹配问题(即CPU 与 I/O 设备速度不匹配的矛盾),分为输入和输出缓冲区。

输入缓冲区会先把客户端发送过来的命令暂存起来,Redis 主线程再从输入缓冲区中读取命令,进行处理。当在处理完数据后,会把结果写入到输出缓冲区,再通过输出缓冲区返回给客户端。

📘 AOF缓冲区: 在进行AOF持久化时所用到的缓冲区,AOF缓冲区消耗的内存取决于AOF重写时间和写入命令量, 分为AOF缓冲区和AOF重写缓冲区

📙 复制缓冲区:是在集群环境中为了保证主从节点数据同步的所设置的,由于主从节点间的数据复制包括全量复制和增量复制两种。因此复制缓冲区也分为复制缓冲区和复制积压缓冲区两种,分别用于全量和增量同步

内存碎片
内存碎片主要是有两个原因:操作系统的内存分配机制、Redis存储特性,这两个原因我们在文章中会具体提到。

子进程消耗
子进程消耗是指在RDB、AOF重写时fork()子进程的内存消耗

有人说这不是用到了写时复制技术吗?

📢 虽然子进程可以不用完全复制父进程的物理内存,但是仍然需要复制其内存页表,在此期间如果有写入操作则需要复制出一份副本出来,因此同样会消耗一部分内存,消耗的内存两取决于RDB和AOF重写期间的写入命令数量。

查看内存指标
查看当前Redis相关内存信息用 info memory 命令,如果是集群使用 cluster info命令

127.0.0.1:6379> info memory
# Memory
used_memory:856472  // Redis 存储数据占用的内存量
used_memory_human:836.40K  // 人类可读形式返回内存总量
used_memory_rss:1282048  // 操作系统角度,进程占用的物理总内存
used_memory_rss_human:1.22M // used_memory_rss 可读性模式展示
used_memory_peak:857448 // 内存使用的最大值,表示 used_memory 的峰值
used_memory_peak_human:837.35K  // 以可读的格式返回 used_memory_peak的值
used_memory_lua:37888   // Lua 引擎所消耗的内存大小。
used_memory_lua_human:37.00K
maxmemory:2147483648    // 能使用的最大内存值,字节为单位。
maxmemory_human:2.00G  // 可读形式
maxmemory_policy:noeviction // 内存淘汰策略

// used_memory_rss / used_memory 的比值,代表内存碎片率
mem_fragmentation_ratio:2.79

used_memory_rss:操作系统分配给 Redis 进程的内存空间(包含内存碎片占用的空间),此数据结果约等于top、ps命令看到的数据结果,是从操作系统层看到的数据

maxmemory:Redis 最大可用内存,0表示不限制,我们一般会设置这个值,避免所有内存超过物理内存

内存为何没释放
Redis 释放的内存空间会由内存分配器管理,并不会立即返回给操作系统,是因为采用了一种称为“惰性删除”的机制,即在数据被删除之后,并不会立即释放内存空间,而是等到有新数据需要使用该空间时才会释放。

这种方式的好处是可以减少内存分配和释放的开销,提高 Redis 的性能。

但是Redis释放内存空间可能不是连续的,**可能导致空间闲置(也就是出现内存碎片),**而内存碎片过大会导致明明有空间可用,但是却无法存储数据!

ok!我们继续看看什么是内存碎片

内存碎片
前面我们已经了解了Redis占用内存的组成以及如何查看内存占用信息,接下来看什么是内存碎片和导致出现内存碎片的原因。

Redis使用多种内存分配策略,例如 jemalloc 和 libc,这些分配器无法做到按需分配,通常会按照固定大小进行分配。例如,如果Redis申请6字节的内存,操作系统会分配8字节的内存给Redis使用,剩下的2个字节空间无法被使用就是内存碎片。

但这种分配方式也有优势,可以减少向操作系统申请空间分配。

导致Redis产生内存碎片主要由以下两点:

• 内存分配机制导致

• 数据修改引发空间扩容和释放

内存分配机制导致
操作系统的架构和 Redis jemalloc 分配策略无法做到按需分配,而是应用程序申请内存大小必须是一块连续的内存地址空间。

这种连续是按固定大小来分配的,比如:8字节、16 字节、32 字节、64 字节 … 这种方式会在程序申请内存接近某个值的时候,jemalloc就会给它分配响应大小的内存空间。
在这里插入图片描述
上图中:

第一次存储数据是需要6字节,而Redis内存分配策略给你分配了8字节,空出2个字节的空间。

第二次存储数据是需要4个字节,但是空出的2个字节无法保存4字节数据,所以会再次向系统申请8字节内存空间,空出了4字节,两次存储数据就多出来6个字节的内存碎片。

这也就是内存分配机制导致的形成碎片的风险和原因。

数据修改引发空间扩容和释放
这个原因应该更好理解吧,若修改数据时占用的空间有变化,此时就需要扩容或者缩容;而删除数据也会将内存释放出来,形成碎片。
在这里插入图片描述
• 各数据占用内存字节空间分别是A:2、B:1、C:3、D:3

• 此时D释放了一个字节空间

• A修改了数据,增加了一个字节。为保证A的内存空间连续性,B的数据拷贝到了第二阶段D释放出来的那个字节位置

• C修改后删除了2个字节空间

可以看出经过一系列对数据的修改,C和D之间有2字段内存空间,此时多出来2字节空间就是内存碎片。

处理内存碎片
如何在进行处理内存碎片,那么以什么为参考呢?

前面说的 info memory命令,如果指标值 mem_fragmentation_ratio (内存碎片率)的值,在 1 < 碎片率 < 1.5,可以认为是合理的,而大于 1.5 说明碎片已经超过 50%,我们需要采取一些手段解决碎片率过大的问题。

有下面三种方式可处理
在这里插入图片描述
重启Redis实例
重启Redis属于直接当时粗暴的方式,在重启之前要考虑两点:

• 若Redis的数据没有持久化,数据会丢失

• 即使做了持久化,重启需要通过AOF或RDB恢复数据,恢复时间取决于日志的大小,如果恢复时间长,这个阶段实例就不能提供服务了

这种方式还是要慎重!

memory purge手动碎片整理
手动整理内存碎片,会阻塞主进程,生产环境慎用。

memory purge 和 activedefrag回收的并不是同一块区域的内存,它简单粗暴的尝试清除脏页以便内存分配器回收。可以根据实际情况和activedefrag配合使用,memory purge在极端情况下效果较好,activedefrag则更彻底。

开启activedefrag自动碎片整理
在Redis 4.0 版本后新增配置项activedefrag,activedefrag默认关闭,计划清理碎片时需手动开启,命令如下:

127.0.0.1:6379> config set activedefrag yes

自动整理内存碎片,其原理是通过scan迭代整个Redis数据,通过一系列的内存复制、转移操作完成内存碎片整理,由于此操作使用的是主线程,故会影响Redis对其他请求的响应。

在这里插入图片描述
如上图碎片整理过程:

  1. 清理前,C和D之间多了2字节的内存碎片

  2. 清理过程:将B和D的数据分别拷贝到C和D之间的闲置空间,这样2个字节的闲置空间就形成了连续空间。当新应用要申请小于3个字节的空间时,这个闲置空间就能利用起来了

清理的条件

active-defrag-ignore-bytes 200mb:内存碎片占用的内存达到 200MB,开始清理;

active-defrag-threshold-lower 20:内存碎片的空间占比超过系统分配给 Redis 空间的 20% ,开始清理

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

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

相关文章

ubuntu22.04 安装cuda

CUDA&#xff08;Compute Unified Device Architecture&#xff09;是由 NVIDIA 开发的一种并行计算平台和编程模型。它允许开发者利用 NVIDIA 的 GPU&#xff08;图形处理单元&#xff09;进行高效的计算处理。CUDA 通过提供一系列的 C、C 和 Fortran 扩展&#xff0c;使得开发…

Navicat 技术指引 | 连接 GaussDB 分布式

Navicat Premium&#xff08;16.3.3 Windows 版或以上&#xff09;正式支持 GaussDB 分布式数据库。GaussDB 分布式模式更适合对系统可用性和数据处理能力要求较高的场景。Navicat 工具不仅提供可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结…

小程序开发要多少钱

随着智能手机的普及和人们对移动应用的需求不断增长&#xff0c;小程序作为一种轻量级应用形式&#xff0c;在商业领域中备受关注。众多企业都渴望抓住这一机遇&#xff0c;但他们最关心的问题之一是&#xff1a;小程序开发需要多少钱&#xff1f; 一、开发方式选择 在开始小…

【LuatOS】笔记(二)基础框架

开发环境搭建 合宙官方搭建的是&#xff1a;vscodeLuatOS-SOC推荐拓展包(vscode插件)&#xff0c;原文链接&#xff1a;LuatOS开发环境搭建。安装完创建项目文件&#xff0c;创建main.lua文件&#xff0c;就可以开始编写了。 函数与使用 LuatOS-SOC接口文档1&#xff0c;该文档…

MongoDB的插入文档、更新文档语句

本文主要介绍MongoDB的插入文档、更新文档语句。 目录 MongoDB插入文档MongoDB更新文档 MongoDB插入文档 在MongoDB中&#xff0c;可以通过使用insertOne或insertMany方法向集合中插入文档。 insertOne方法可以插入一个文档&#xff0c;例如&#xff1a; db.collection.inse…

【深度学习】一维数组的聚类

在学习聚类算法的过程中&#xff0c;学习到的聚类算法大部分都是针对n维的&#xff0c;针对一维数据的聚类方式较少&#xff0c;今天就来学习下如何给一维的数据进行聚类。 方案一&#xff1a;采用K-Means对一维数据聚类 Python代码如下&#xff1a; from sklearn.cluster im…

【Cisco Packet Tracer】路由器实验 静态路由/RIP/OSPF/BGP

本教程讲解路由器的静态IP配置、RIP、OSPF、BGP等实验内容。 一、基本设置 绘制以下拓扑结构&#xff1a; PC0设置&#xff1a; PC1设置&#xff1a; Router0端口0设置&#xff1a; Router0端口1设置&#xff1a; Router1端口0设置&#xff1a; Router1端口1设置&#xff1a…

Elasticsearch:使用 Elasticsearch 向量搜索及 RAG 来实现 Chatbot

Elasticsearch 的向量搜索为我们的语义搜索提供了可能。而在人工智能的动态格局中&#xff0c;检索增强生成&#xff08;Retrieval Augmented Generation - RAG&#xff09;已经成为游戏规则的改变者&#xff0c;彻底改变了我们生成文本和与文本交互的方式。 RAG 使用大型语言模…

PR剪辑视频做自媒体添加字幕快速方式(简单好用的pr视频字幕模板)

如何选择合适的字幕添加进短视频呢&#xff1f;首先要先确定增加的视频风格&#xff0c;简约、商务、科技感、炫酷&#xff1b;再确定用途&#xff0c;注释、标记、语音翻译、引用、介绍&#xff1b;最后在相应的模板中挑选几个尝试&#xff0c;悬着一个最切合主题的使用&#…

数据结构——队列

目录 一、队列的定义 二、队列的实现 1. 队列的顺序存储结构 1.1. 顺序队 1. 创建顺序队 2. 删除顺序队 3. 判断队列是否为空 4. 判断队列是否已满 5. 入队 6. 出队 7. 获取队列长度 8. 获取队首元素 1.2. 环形队 1. 创建环形队 2. 删除环形队 3. 判断环形队列…

QMenu风格设计qss+阴影

Qt的菜单经常在软件开发中用到&#xff0c;默认的菜单效果都不符合设计师的要求&#xff0c;本篇介绍QMenu菜单的风格设计&#xff0c;包括样式表和阴影。 1.QMenu样式表的设计 首先看一个默认的菜单 void QGraphicsDropShadowEffectDemo::slotShowDialog() {qDebug() <&l…

Navicat 技术指引 | 适用于 GaussDB 分布式的查询功能

Navicat Premium&#xff08;16.3.3 Windows 版或以上&#xff09;正式支持 GaussDB 分布式数据库。GaussDB 分布式模式更适合对系统可用性和数据处理能力要求较高的场景。Navicat 工具不仅提供可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结…

关于前端原生技术-Jsonp的理解与简述

【版权声明】未经博主同意&#xff0c;谢绝转载&#xff01;&#xff08;请尊重原创&#xff0c;博主保留追究权&#xff09; https://blog.csdn.net/m0_69908381/article/details/134777717 出自【进步*于辰的博客】 在学习了Jsoup这个知识点之后&#xff0c;发觉js的这一特点…

智慧社区前景无限,科技引领未来发展

社区是城镇化发展的标志&#xff0c;作为人类现代社会的生活的基本圈子&#xff0c;是人类生活离不开的地方&#xff0c;社区人口密度大、车辆多&#xff0c;管理无序&#xff0c;社区的膨胀式发展多多少少带来一定的管理上的缺失。社区作为智慧城市建设的重要一环&#xff0c;…

idea__SpringBoot微服务05——JSR303校验(新注解)(新的依赖),配置文件优先级,多环境切换

JSR303校验&#xff0c;配置文件优先级&#xff0c;多环境切换 一、JSR303数据校验二、配置文件优先级三、多环境切换一、properties多环境切换二、yaml多环境切换————————创作不易&#xff0c;如觉不错&#xff0c;随手点赞&#xff0c;关注&#xff0c;收藏(*&#x…

【Linux】无法使用 ifconfig 查看系统网络接口信息,报错 command not found: ifconfig

问题描述 ifconfig是一个用于配置和显示系统网络接口信息的命令行工具。它通常用于Unix、Linux和其他类Unix系统中。 通过ifconfig命令&#xff0c;你可以查看和修改系统中网络接口的配置信息&#xff0c;包括IP地址、子网掩码、MAC地址、MTU&#xff08;最大传输单元&#x…

IDEA 社区版 add GitLab Account

问题 IntelliJ IDEA Community Edition 2023.3&#xff08;社区版&#xff09;在使用GitLab连接时&#xff0c;使用个人访问令牌出现报错&#xff0c;代码&#xff1a; GraphQL error:[No such type ProjectMember,so it cant be a fraggment condition,Field id doesnt exis…

STM32 map文件详解

文章目录 1. 前言2. 生成 .map 文件3 .map 文件的组成3.1 Section Cross References - 各个源文件之间函数的调用关系3.2 Removing Unused input sections from the image - 移除未使用的模块3.3 Image Symbol Table - 映射符号表&#xff1a;描述各&#xff08;程序段 / 数据&…

【Fastadmin】一个完整的轮播图功能示例

目录 1.效果展示&#xff1a; 列表 添加及标记页面同 2.建表&#xff1a; 3.时候crud一键生成并创建控制器 4.html页面 add.html edit.html index.php 5.js页面 6.小知识点 1.效果展示&#xff1a; 列表 添加及标记页面同 2.建表&#xff1a; 表名&#xff1a;fa_x…

Cocos Creator:必知必会

Cocos Creator&#xff1a;必知必会 事件事件属性坐标系的区别 持续更新中。。。 事件 开发版本&#xff1a;v3.8.1 事件属性 坐标系的区别 在Cocos游戏开发框架中&#xff0c;getLocation和getUILocation是两个用于获取节点位置的方法&#xff0c;但是它们之间存在一些重要…
最新文章