共计 1215 个字符,预计需要花费 4 分钟才能阅读完成。
上周刚来了个应届小师弟,组长说让我带着,周二问了我这样一个问题:师兄啊,我用 top 命令看了下服务器的内存占用状况,发现 Redis 内存占用重大,于是我就删除了大部分不必的 keys,为什么内存占用还是很重大,并没有开释呢?
嗯?为什么呢?明天就带着这个问题来介绍一下如何正确开释 Redis 的内存。
什么是内存碎片?
内存碎片这个概念应该不是第一据说了,相熟 JVM 或者操作系统的应该都相熟,以火车卖票为例,一个车厢 128 个车位,因为高峰期,只残余流量交易两个地位了,然而此时三个人想要坐在一起,可能吹吹牛批,喝喝酒的,那么这三个人必定不会买这节车厢的两个地位了,此时这两个地位能够称之为座位碎片。
操作系统中对于内存调配也是一样的,比方利用须要申请一块间断 N 个字节的空间,尽管残余内存总量大于 N 个字节,然而没有一块间断的内存空间是 N 个字节,那么残余的空间就是内存碎片。
那么什么起因会造成内存碎片呢?这个其实大抵分为两个起因,一个是操作系统的内存调配策略,一个是 Redis 本身起因,上面就这两个起因详细分析。
内存分配器的调配策略
内存分配器的调配策略个别是依照固定大小来分配内存,而不是依照应用程序申请的内存空间按需分配。比方 8 字节、16 字节、32 字节 ……
Redis 提供了多种的内存调配策略,比方 libc、jemalloc、tcmalloc,默认应用 jemalloc。
jemalloc 这种调配策略,是依照固定的空间调配,比方 8 字节、32 字节 ….2KB、4KB 等。当应用程序申请的内存靠近某个固定值的时候,jemalloc 则会调配固定的大小。比方申请了 6 字节,则会调配 8 字节的空间。
这种调配的形式的益处很显著,则会缩小内存调配的次数,比方申请了 20 字节的内存,理论调配的是 32 字节的内存空间,当利用再写入 10 字节的数据时,则不会再次调配,残余的 12 字节足够用了。这样就防止了一次的内存调配。
然而害处也很显著,申请的和调配的空间不一样,则残余的空间很可能造成内存碎片,一旦内存碎片多了,内存利用率也会随之升高,这是很可怕的。
Redis 本身的起因
Redis 作为键值对存储的数据库,自身键值对的大小就是不确定的,正如下面的例子中,Redis 申请了 20 字节的空间,但理论调配却是 32 字节,那么残余的 12 字节则会被闲置成为内存碎片
如何判断存在内存碎片?
这个对于运维人员来说很重要,一旦呈现 Redis 运行迟缓或者阻塞了,肯定须要先判断内存的占用状况,而不是说胡乱的重启 Redis。
Redis 本身提供了 INFO 命令,能够用来查问内存的应用状况,命令如下:
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