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

news2025/5/15 5:50:22

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.coloradmin.cn/o/1297145.html

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

相关文章

QQ2023备份

需要修改的路径&#xff08;共3处&#xff09; 这三处路径中&#xff0c;只有一处是需要修改的 QQPC端-主菜单-设置-基本设置-文件管理 点击上面的“”自定义“”&#xff0c;然后修改路径即可 修改路径后提示 然后等一会才会关干净QQ的相关进程&#xff0c;关闭后才会有自动…

Windows的C盘爆掉了怎么办?

本文参考&#xff1a; C盘太满怎么办&#xff1f;亲测8种好用方法&#xff01; 如果C盘的分区爆掉了&#xff0c;变红色了&#xff0c;是时候该处理这个问题了&#xff0c;解决你的C盘焦虑&#xff01; 第一招&#xff1a;删除C盘文件 首先你会想到清理C盘里面的文件&#x…

Flink入门之核心概念(三)

任务槽 TaskSlots: 任务槽&#xff0c;是TaskManager提供的用于执行Task的资源&#xff08;CPU 内存&#xff09; TaskManager提供的TaskSlots的个数&#xff1a;主要由Taskmanager所在机器的CPU核心数来决定&#xff0c;不能超过CPU的最大核心数 1.可以在flink/conf/flink-c…

【C++】map/multimap/set/multiset的经典oj例题 [ 盘点&全面解析 ] (28)

前言 大家好吖&#xff0c;欢迎来到 YY 滴C系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; 目录 一.前K个高频单词【mutiset】二.左右符…

云服务器Centos中安装Docker

云服务器Centos中安装Docker 1 简介DockerCentosCentos和Ubuntu区别 2 安装3 测试hello-world的镜像测试 1 简介 Docker Docker是一个开源的应用容器引擎&#xff0c;利用操作系统本身已有的机制和特性&#xff0c;可以实现远超传统虚拟机的轻量级虚拟化。它支持将软件编译成…

虚拟机-桥接模式连接

文章目录 1.查看宿主机再用的IP信息2.桥接模式-虚拟机设置VMware设置虚拟机设置重启网络服务 1.查看宿主机再用的IP信息 ipconfig /all 注&#xff1a; 在虚拟机中要设置同网段的ip设置同一个子网掩码设置同一个网关设置同一个DNS服务器 2.桥接模式-虚拟机设置 VMware设置 虚…

整数在内存中的存储

整数和浮点数在内存中的存储方式是不一样的&#xff0c;今天&#xff0c;我们来具体学习一下 文章目录 整数在内存中的存储浮点数在内存中的存储 整数在内存中的存储 我们在之前就已经了解过了整数有原码&#xff0c;反码&#xff0c;补码的形式&#xff0c;这三种方式都是二进…

cache教程 2.单机并发缓存

0.对原教程的一些见解 个人认为原教程中两点知识的引入不够友好。 首先是只读数据结构 ByteView 的引入使用是有点迷茫的&#xff0c;可能不能很好理解为什么需要ByteView。 第二是主体结构 Group的引入也疑惑。其实要是熟悉groupcache&#xff0c;那对结构Group的使用是清晰…

LangChain学习二:提示-实战

文章目录 上一节内容&#xff1a;LangChain学习一&#xff1a;模型-实战学习目标&#xff1a;提示词及提示词模板的运用学习内容一&#xff1a;什么是提示词&#xff1f;学习内容二&#xff1a;提示词模板2.1 聊天提示模板实战:首先需要声明和定义一个模板实战:把提示词模板放入…

分类预测 | GASF-CNN格拉姆角场-卷积神经网络的数据分类预测

分类预测 | GASF-CNN格拉姆角场-卷积神经网络的数据分类预测 目录 分类预测 | GASF-CNN格拉姆角场-卷积神经网络的数据分类预测分类效果基本描述模型描述程序设计参考资料 分类效果 基本描述 1.GASF-CNN格拉姆角场-卷积神经网络的数据分类预测&#xff08;完整源码和数据) 2.自…

Leetcode2477. 到达首都的最少油耗

Every day a Leetcode 题目来源&#xff1a;2477. 到达首都的最少油耗 解法1&#xff1a;贪心 深度优先搜索 题目等价于给出了一棵以节点 0 为根结点的树&#xff0c;并且初始树上的每一个节点上都有一个人&#xff0c;现在所有人都需要通过「车子」向结点 0 移动。 对于…

os.walk()遍历文件夹/文件

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

智能优化算法应用:基于人工蜂鸟算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于人工蜂鸟算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于人工蜂鸟算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.人工蜂鸟算法4.实验参数设定5.算法结果6.参考…

Qt槽函数不响应不执行的一种原因:ui提升导致重名

背景&#xff1a; 一个包含了组件提升的ui&#xff0c;有个按钮的槽函数就是不响应&#xff0c;于是找原因。 分析&#xff1a; 槽函数的对应一是通过connect函数绑定信号&#xff0c;二是on_XXX_signal的命名方式。界面上部件的槽函数通常是第二种。 我反复确认细节&#…

正则表达式:字符串处理的瑞士军刀

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

图的搜索(一):广度优先搜索算法和深度优先搜索算法

图的搜索&#xff08;一&#xff09;&#xff1a;广度优先搜索算法和深度优先搜索算法 本章主要记录了图的搜索算法&#xff0c;和可以解决图的基本问题——最短路径问题的算法。本章主要对图搜索的相关算法进行了介绍&#xff1a;广度优先搜索算法、深度优先搜索算法。 下一…

蓝牙物联网开发应用实例|「蓝牙道钉」规范共享单车停放

为进一步改善城市环境&#xff0c;解决共享单车乱停乱放、随意占道等顽疾&#xff0c;引导骑行者文明停放&#xff0c;近期&#xff0c;铜陵市试点启用共享单车“蓝牙道钉”技术。 共享单车“蓝牙道钉”是通过在人行便道的停放区域内安装“道钉”设备&#xff0c;凭借蓝牙高精…

电视节目中活动灭灯系统是如何实现的

活动灭灯系统主要用于各种需要亮灯或灭灯的活动节目&#xff0c;如招聘灭灯、相亲灭灯等。有多种灯光颜色供选择&#xff0c;本设备通过按钮灯软件组合实现&#xff0c;用户可以自己设置亮灯或灭灯规则。 软件功能&#xff1a; 1、后台统一控制亮灯&#xff0c;重新开始下轮…

three.js 入门三:buffergeometry贴图属性(position、index和uvs)

环境&#xff1a; three.js 0.159.0 一、基础知识 geometry&#xff1a;决定物体的几何形状、轮廓&#xff1b;material&#xff1a;决定物体呈现的色彩、光影特性、贴图皮肤&#xff1b;mesh&#xff1a;场景中的物体&#xff0c;由geometry和materia组成&#xff1b;textu…

虹科Pico汽车示波器 | 汽车免拆检修 | 2018款东风风神AX7车发动机怠速抖动、加速无力

一、故障现象 一辆2018款东风风神AX7车&#xff0c;搭载10UF01发动机&#xff0c;累计行驶里程约为5.3万km。该车因发动机怠速抖动、加速无力及发动机故障灯异常点亮而进厂维修&#xff0c;维修人员用故障检测仪检测&#xff0c;提示气缸3失火&#xff1b;与其他气缸对调点火线…