基本概念
-
基本概念
- 当数据删除后,Redis 释放的内存空间会由内存分配器管理(不适用java gc的原因之一?),并不会立即返回给操作系统(从操作系统的视角看)
-
内存不回收存在的问题
- Redis 释放的内存空间可能并不是连续
- 不能保存合适的数据
- 不仅会减少 Redis 能够实际保存的数据量,还会降低 Redis 运行机器的成本回报率
什么是内存碎片?
-
内存空间闲置,往往是因为操作系统发生了较为严重的内存碎片\
- 虽然是空着的,但是不满足大部分分配的需求
- 应用申请的是一块连续地址空间的 N 字节,但在剩余的内存空间中,没有大小为 N 字节的连续空间了\
-
只有了解了内存碎片的成因,才能对症下药,把 Redis 占用的内存空间充分利用起来,增加存储的数据量\
内存碎片是如何形成的?
-
内因:内存分配器的分配策略
-
内存分配器是按照固定大小分配内存,而不是申请多大及多大
-
redis可用的分配器
-
libc\
-
jemalloc 默认\
-
当程序申请的内存最接近某个固定值时,jemalloc 会给它分配相应大小的空间\
-
避免了频繁分配
-
-
tcmalloc
-
-
-
外因:键值对大小不一样和删改操作(不停的扩容与删除)
-
Redis 申请内存空间分配时,本身就会有大小不一的空间需求\
-
[1]分配的内存空间一般都会比申请的空间大一些,不会完全一致\
-
[2]这些键值对会被修改和删除,这会导致空间的扩容和释放
-
如何判断是否有内存碎片?
\
-
使用Info命令可以查看内存碎片
-
mem_fragmentation_ratio 表示内存碎片率\
-
是利用used_memory_rss(从操作系统获取)/used_memory(实际使用)相除的结果
-
-
正常的区间
-
mem_fragmentation_ratio 大于 1 但小于 1.5 属于正常情况\
-
mem_fragmentation_ratio 大于 1.5 不可以接收,内存碎片率已经超过了 50%(正常使用的一半)\
-
-
\
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
如何清理内存碎片?
-
方法1:重启redis
-
缺点:
- reids中的数据未持久化,会造成数据丢失
- 需要通过AOF和RDB进行恢复,无法提供服务
-
-
方法2:使用reids自带内存碎片清理 4.0-RC3 版本以后
-
实现原理:搬家让位,合并空间(类似于GC的复制算法)
-
缺点:碎片清理是有代价的:拷贝数据并释放空间会导致时间开销,阻塞redis的单线程\
-
优化:Redis 专门为自动内存碎片清理功机制设置的参数
-
原理:我们可以通过设置参数,来控制碎片清理的开始和结束时机,以及占用的 CPU 比例,从而减少碎片清理对 Redis 本身请求处理的性能影响\
-
1.Redis 需要启用自动内存碎片清理,可以把 activedefrag 配置项设置为 yes config set activedefrag yes
-
2.active-defrag-ignore-bytes 100mb:表示内存碎片的字节数达到 100MB 时,开始清理
-
3.active-defrag-threshold-lower 10:表示内存碎片空间占操作系统分配给 Redis 的总空间比例达到 10% 时,开始清理
-
4.active-defrag-cycle-min 25: 表示自动清理过程所用 CPU 时间的比例不低于 25%,保证清理能正常开展
-
5.active-defrag-cycle-max 75:表示自动清理过程所用 CPU 时间的比例不高于 75%,一旦超过,就停止清理,从而避免在清理时,大量的内存拷贝阻塞 Redis,导致响应延迟升高
-
-
\
总结
-
内存碎片优化,可以提升内存利用率,放入更多的元素
-
info memory 命令是一个好工具,可以帮助你查看碎片率的情况\
-
碎片率阈值是一个好经验,可以帮忙你有效地判断是否要进行碎片清理了\
-
内存碎片自动清理是一个好方法,可以避免因为碎片导致 Redis 的内存实际利用率降低,提升成本收益率\
-
\