Redis 删除数据后不能自动释放内存的问题
Redis做系统缓存,历史原因缓存策略和缓存内容不太适应增长的业务量,死皮赖脸扛着dba各种dissN个日日夜夜后决定清理一波僵尸。
但将无用的key删除后,并没有真正的释放内存,查看Redis的相关文档,也没有释放内存的相关命令。看着仪表盘的百分比甚是挠头。。。
查了些资料了解了下,改日再请教请教dba大大们。。。
官方已经说了具体原因
https://redis.io/topics/memory-optimization
概括了点内容:
这不是Redis本身的问题,Redis本身确实已经调用free释放这些内存。这应该是使用的底层C运行时的问题。
当键被删除时,Redis并不总是释放(返回)内存到操作系统。这并不是Redis的特别之处,但大多数malloc()实现都是这样工作的。
例如一个实例有5gb的数据,然后删除相当于2gb的数据,used_memory_rss可能仍会5 gb左右。这是因为底层分配器不能轻松地释放内存。例如,通常将删除的大多数键分配到与其他仍然存在的键相同的页面中。
然而分配器是聪明和能够重用空闲块的内存,所以在你释放2 gb的5 gb的数据集,当你开始再次增加键,您将看到used_memory_rss保持稳定而不会再增加很多。分配器基本上是尝试重用以前(逻辑上)释放的2GB内存。
就glibc来说,在分配大于128k的内存时使用mmap,而使用brk/sbrk在heap中分配小内存。通过mmap申请的内存在调用free后能马上返还给系统,而heap中的内存就不一定,除非释放的内存是heap中连续的大块。
Redis本身没有内存管理机制,只有一个使用量的统计功能 。每次需要创建对象,都是直接调用malloc申请,而Redis中的对象基本都比较小,所以基本都是在heap中的内存。
解决方案
通过原因可以知道,我们其实不用去关注。
特别是我们定义了maxmemory后,并且定义了maxmemory_policy,那么即使内存满了,redis也会按照淘汰机制方案,清除一些不需要的key,来存放新的key。
但是如果已经影响到系统内存使用了,也有下面三种方案:
- 可以通过 MEMORY PURGE命令进行内存整理。(瞬时,能稍微腾出rss内存空间)
- 开启activedefrag,热碎片整理。(会占用CPU,在主线程执行,可以设置CPU占用率)
- 重启。
看了解决方案,然后还是去请教dba大大吧。。。。