0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Redis的数据被删除,内存占用还这么大?

OSC开源社区 来源:OSC开源社区 作者:OSC开源社区 2022-12-14 10:56 次阅读

操作系统分配给 Redis 的内存有 6GB,通过指标 used_memory_human 发现存储数据只使用了 4GB,为何会这样?为何无法保存数据?

通过 CONFIG SET maxmemory 100mb或者在 redis.conf 配置文件设置 maxmemory 100mb Redis 内存占用限制。当达到内存最大值,会触发内存淘汰策略删除数据。

除此之外,当 key 达到过期时间,Redis 会有以下两种删除过期数据的策略:

  • 后台定时任务选取部分数据删除;
  • 惰性删除。

具体原理请移步《Redis 的过期数据删除那些事》。

假设 Redis 实例保存了 5GB 的数据,现在删除了 2GB 数据,Redis 进程占用的内存一定会降低么?(也叫做 RSS,进程消耗内存页数)。

答案是:可能依然占用了大约 5GB 的内存,即使 Redis 的数据只占用了 3GB 左右。

大家一定要设置maxmemory,否则 Redis 会继续为新写入的数据分配内存,无法分配就会导致应用程序报错,当然不会导致宕机。

释放的内存去哪了

明明删除了数据,使用 top 命令查看,为何还是占用了那么多内存?

内存都去哪了?使用 info memory 命令获取 Redis 内存相关指标,我列举了几个重要的数据:

127.0.0.1:6379>infomemory
#Memory
used_memory:1132832//Redis存储数据占用的内存量
used_memory_human:1.08M//人类可读形式返回内存总量
used_memory_rss:2977792//操作系统角度,进程占用的物理总内存
used_memory_rss_human:2.84M//used_memory_rss可读性模式展示
used_memory_peak:1183808//内存使用的最大值,表示used_memory的峰值

used_memory_peak_human:1.13M//以可读的格式返回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

Redis 进程内存消耗主要由以下部分组成:

  • Redis 自身启动所占用的内存;
  • 存储对象数据内存;
  • 缓冲区内存:主要由 client-output-buffer-limit 客户端输出缓冲区、复制积压缓冲区、AOF 缓冲区。
  • 内存碎片。
0fff447e-7b2d-11ed-8abf-dac502259ad0.png内存占用

Redis 自身空进程占用的内存很小可以忽略不计,对象内存是占比最大的一块,里面存储着所有的数据。

缓冲区内存在大流量场景容易失控,造成 Redis 内存不稳定,需要重点关注。

内存碎片过大会导致明明有空间可用,但是却无法存储数据。

碎片 = used_memory_rss 实际使用的物理内存(RSS 值)除以 used_memory 实际存储数据内存。

什么是内存碎片

内存碎片会造成明明有内存空间空闲,可是却无法存储数据。举个例子,你跟漂亮小姐姐去电影院看电影,肯定想连在一块。

假设现在有 8 个座位,已经卖出了 4 张票,还有 4 张可以买。可是好巧不巧,买票的人很奇葩,分别间隔一个座位买票。

即使还有 4 个座位空闲,可是你却买不到两个座位连在一块的票,厚礼蟹!

100bfe30-7b2d-11ed-8abf-dac502259ad0.png内存碎片

内存碎片形成原因

内存碎片是什么原因导致呢?

主要有两个原因:

  • 内存分配器的分配策略。
  • 键值对的大小不一样和删改操作:Redis 频繁做更新操作、大量过期数据删除,释放的空间(不够连续)无法得到复用,导致碎片率上升。

接下来我分别探讨实际发生的原因……

内存分配器的分配策略

Redis 默认的内存分配器采用 jemalloc,可选的分配器还有:glibc、tcmalloc。

内存分配器并不能做到按需分配,而是采用固定范围的内存块进行分配。

例如 8 字节、16 字节…..,2 KB,4KB,当申请内存最近接某个固定值的时候,jemalloc 会给它分配最接近固定值大小的空间。

这样就会出现内存碎片,比如程序只需要 1.5 KB,内存分配器会分配 2KB 空间,那么这 0.5KB 就是碎片。

这么做的目的是减少内存分配次数,比如申请 22 字节的空间保存数据,jemalloc 就会分配 32 字节,如果后边还要写入 10 字节,就不需要再向操作系统申请空间了,可以使用之前申请的 32 字节。

删除 key 的时候,Redis 并不会立马把内存归还给操作系统,出现这个情况是因为底层内存分配器管理导致,比如大多数已经删除的 key 依然与其他有效的 key 分配在同一个内存页中。

另外,分配器为了复用空闲的内存块,原有 5GB 的数据中删除了 2 GB 后,当再次添加数据到实例中,Redis 的 RSS 会保持稳定,不会增长太多。

因为内存分配器基本上复用了之前删除释放出来的 2GB 内存。

键值对大小不一样和删改操作

由于内存分配器是按照固定大小分配内存,所以通常分配的内存空间比实际数据占用的大小多一些,会造成碎片,降低内存的存储效率。

另外,键值对的频繁修改和删除,导致内存空间的扩容和释放,比如原本占用 32 字节的字符串,现在修改为占用 20 字节的字符串,那么释放出的 12 字节就是空闲空间。

如果下一个数据存储请求需要申请 13 字节的字符串,那么刚刚释放的 12 字节空间无法使用,导致碎片。

碎片最大的问题:空间总量足够大,但是这些内存不是连续的,可能大致无法存储数据。

内存碎片解决之道

那该如何解决呢?

首先要确定是否发生了内存碎片,重点关注前面 INFO memory 命令提示的 mem_fragmentation_ratio 指标,表示内存碎片率:

mem_fragmentation_ratio=used_memory_rss/used_memory

如果 1 < 碎片率 < 1.5,可以认为是合理的,而大于 1.5 说明碎片已经超过 50%,我们需要采取一些手段解决碎片率过大的问题。

重启大法

最简单粗暴的方式就是重启,如果没有开启持久化,数据会丢失。

开启持久化的话,需要使用 RDB 或者 AOF 恢复数据,如果只有一个实例,数据大的话会导致恢复阶段长时间无法提供服务,高可用大打折扣。

咋办呢?码哥靓仔

自动清理内存碎片

既然你都叫我靓仔了,就倾囊相助告诉你终极杀招:Redis 4.0 版本后,自身提供了一种内存碎片清理机制。

怎么清理呢?

很简单,还是上面的例子,想要买两张连在一块的电影票。与与别人沟通调换下位置,就实现了。

对于 Redis 来说,当一块连续的内存空间被划分为好几块不连续的空间的时候,操作系统先把数据以依次挪动拼接在一块,并释放原来数据占据的空间,形成一块连续空闲内存空间。。

如下图所示:

1015184e-7b2d-11ed-8abf-dac502259ad0.png碎片清理

自动清理内存碎片的代价

自动清理虽好,可不要肆意妄为,操作系统把数据移动到新位置,再把原有空间释放是需要消耗资源的。

Redis 操作数据的指令是单线程,所以在数据复制移动的时候,只能等待清理碎片完成才能处理请求,造成性能损耗。

如何避免清理碎片对性能的影响又能实现自动清理呢?

好问题,通过以下两个参数来控制内存碎片清理和结束时机,避免占用 CPU 过多,减少清理碎片对 Redis 处理请求的性能影响。

开启自动内存碎片清理

CONFIGSETactivedefragyes

这只是开启自动清理,何时清理要同时满足以下两个条件才会触发清理操作。

清理的条件

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

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

避免对性能造成影响

清理时间有了,还需要控制清理对性能的影响。由一项两个设置先分配清理碎片占用的 CPU 资源,保证既能正常清理碎片,又能避免对 Redis 处理请求的性能影响。

active-defrag-cycle-min 20:自动清理过程中,占用 CPU 时间的比例不低于 20%,从而保证能正常展开清理任务。

active-defrag-cycle-max 50:自动清理过程占用的 CPU 时间比例不能高于 50%,超过的话就立刻停止清理,避免对 Redis 的阻塞,造成高延迟。

总结

如果你发现明明 Redis 存储数据的内存占用远小于操作系统分配给 Redis 的内存,而又无法保存数据,那可能出现大量内存碎片了。

通过 info memory 命令,看下内存碎片mem_fragmentation_ratio 指标是否正常。

那么我们就开启自动清理并合理设置清理时机和 CPU 资源占用,该机制涉及到内存拷贝,会对 Redis 性能造成潜在风险。

如果遇到 Redis 性能变慢,排查下是否由于清理碎片导致,如果是,那就调小 active-defrag-cycle-max 的值。

审核编辑 :李倩

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 操作系统
    +关注

    关注

    37

    文章

    6825

    浏览量

    123333
  • 分配器
    +关注

    关注

    0

    文章

    194

    浏览量

    25755
  • Redis
    +关注

    关注

    0

    文章

    375

    浏览量

    10878

原文标题:Redis的数据被删除,内存占用还这么大?

文章出处:【微信号:OSC开源社区,微信公众号:OSC开源社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Redis缓存与Memcached的比较

    Redis和Memcached都是广泛使用的内存数据存储系统,它们主要用于提高应用程序的性能,通过减少对数据库的直接访问来加速数据检索。以下
    的头像 发表于 12-18 09:33 148次阅读

    如何优化RAM内存使用

    :使用任务管理器查看当前运行的程序和服务,关闭那些不需要的。 禁用启动程序 :减少开机启动项,只保留必要的程序。 2. 优化操作系统设置 调整虚拟内存 :合理设置虚拟内存,避免过多占用硬盘空间。 清理磁盘 :定期进行磁盘清理,
    的头像 发表于 11-11 09:58 354次阅读

    恒讯科技分析:云数据库rds和redis区别是什么如何选择?

    结构化数据,使用SQL作为查询语言,支持ACID事务和多种复杂查询操作。而Redis是一个基于内存的非关系型数据库,采用键值对模型存储数据
    的头像 发表于 08-19 15:31 398次阅读

    NetApp数据恢复—NetApp存储误删除数据恢复案例

    某公司一台NetApp存储,该存储中有24块磁盘。 工作人员误删除了NetApp存储中一个文件夹,文件夹中有非常重要的数据数据恢复工程师在现场对该存储进行了初检。虽然这个文件夹被删除
    的头像 发表于 08-12 13:35 274次阅读
    NetApp<b class='flag-5'>数据</b>恢复—NetApp存储误<b class='flag-5'>删除</b>的<b class='flag-5'>数据</b>恢复案例

    mesh的内存占用能否优化?

    我测试到esp_mesh在开启的情况下,即打开wifi和打开mesh,DRAM会占用大约130kb内存。且测试发现esp32剩余内存不足大约60kb的时候系统会重启。这样来说300KB内存
    发表于 06-28 15:32

    服务器数据恢复—EMC Isilon存储中虚拟机数据恢复案例

    、AS、TS类型的视频文件等。需要恢复数据的虚拟机通过NFS协议共享到ESX主机,视频文件通过CIFS协议共享给虚拟机(WEB服务器)。 通过NFS协议共享的所有数据(虚拟机)被删除,而通过CIFS协议共享的
    的头像 发表于 06-13 13:38 397次阅读
    服务器<b class='flag-5'>数据</b>恢复—EMC Isilon存储中虚拟机<b class='flag-5'>数据</b>恢复案例

    服务器数据恢复—存储中卷被删除后重建如何恢复被删除卷的数据

    服务器存储数据恢复环境: 某品牌FlexStorage P5730服务器存储,存储中有一组由24块硬盘组建的RAID5阵列,包括1块热备硬盘。 服务器存储故障: 存储中的2个卷被删除删除之后重建了一个新卷。需要恢复之
    的头像 发表于 06-05 11:03 661次阅读

    NetApp数据恢复—WAFL文件系统下误删除数据数据恢复案例

    某公司NetApp存储设备,人为误操作导致NetApp存储内部分重要数据被删除,该NetApp存储采用WAFL文件系统,底层是由多块硬盘组成的raid阵列。
    的头像 发表于 05-13 10:50 375次阅读

    Redis为什么这么快?

    Redis 是基于内存数据库,那不可避免的就要与磁盘数据库做对比。对于磁盘数据库来说,是需要将数据
    发表于 04-12 10:32 216次阅读
    <b class='flag-5'>Redis</b>为什么<b class='flag-5'>这么</b>快?

    linux下查询进程占用内存方法有哪些?

    linux下查询进程占用内存方法
    发表于 04-08 06:03

    Redis开源版与Redis企业版,怎么选用?

    点击“蓝字”关注我们数以千计的企业和数以百万计的开发人员Redis开源版来构建应用程序。但随着用户数量、数据量和地区性的增加,成本、可扩展性、运营和可用性等问题也随之而来。Redis企业版
    的头像 发表于 04-04 08:04 1073次阅读
    <b class='flag-5'>Redis</b>开源版与<b class='flag-5'>Redis</b>企业版,怎么选用?

    数据安全没保障?GaussDB(for Redis) 为你保驾护航

    未知的 key,实际上可能面临数据库信息丢失和记录篡改的风险。 作为一个重视技术的团队,我们始终将用户信息安全和使用体验放在第一位。对于这次用户使用开源 Redis 遇到的问题,我们盘点了 GaussDB(for Redis)精
    的头像 发表于 03-28 22:09 676次阅读
    <b class='flag-5'>数据</b>安全没保障?GaussDB(for <b class='flag-5'>Redis</b>) 为你保驾护航

    在MDK中使用RTT为什么内存占用这么大?

    为什么在MDK中使用RTT ,内存占用这么大?
    发表于 02-26 07:19

    MongoDB和Redis的技术特性

    Redis作为一个高性能的内存数据存储系统,能够提供快速的缓存机制,从而帮助应用承受高并发请求,显著提高系统响应速度和吞吐量。这与国内互联网公司推崇的快速迭代和高用户并发量的特点非常契合。
    的头像 发表于 02-01 11:42 507次阅读
    MongoDB和<b class='flag-5'>Redis</b>的技术特性

    一分钟,自动完成Redis数据迁移

    化的数据迁移过程。NineData还提供了观测和干预能力,帮助用户追踪迁移进展,并提供诊断和迁移限流能力,保障迁移的稳定性。除了Redis,NineData支持多种常见数据库的迁移复
    的头像 发表于 01-08 11:34 430次阅读
    一分钟,自动完成<b class='flag-5'>Redis</b><b class='flag-5'>数据</b>迁移