Redis支持3内存分配器:libc,jemalloc,tcmalloc。当我进行内存使用测试时,我发现 INFO MEMORY 中的 mem_fragmentation_ratio 在libc分配器中可能小于1。使用jemalloc或tcmalloc时,此值应大于或等于1。
有没有人可以用libc解释为什么 mem_fragmentation_ratio 小于1?
Redis版本:2.6.12。 CentOS 6
更新
我忘了提到一个可能的原因是交换发生并且 mem_fragmentation_ratio 将< 1。
但是,当我进行测试时,我会调整交换,甚至关闭交换。结果是一样的。而我的redis实例实际上并没有花费太多内存。
答案 0 :(得分:2)
通常,与libc malloc相比,使用jemalloc或tcmalloc的碎片更少。这是由于4个因素:
jemalloc和tcmalloc的更精细的分配类。它减少了内部碎片,特别是当Redis必须分配很多非常小的对象时。
更好的算法和数据结构,以防止外部碎片(特别是对于jemalloc)。显然,增益取决于你的长期记忆分配模式。
支持“malloc size”。一些分配器提供API来返回已分配内存的大小。使用glibc(Linux),malloc没有此功能,因此可以通过为每个分配的内存块显式添加额外的前缀来模拟它。它增加了内部碎片。使用jemalloc和tcmalloc(或使用BSD libc malloc),没有这样的 开销。
jemalloc(以及带有一些设置更改的tcmalloc)可以比glibc更积极地向操作系统释放内存 - 但同样,它取决于分配模式。
现在,如何为mem_fragmentation_ratio获取不一致的值?
如the INFO documentation中所述,mem_fragmentation_ratio值计算为进程的内存驻留集大小(RSS,由OS测量)与Redis使用分配器分配的总字节数之间的比率。
现在,如果使用libc分配更多内存(与jemalloc,tcmalloc相比),或者在基准测试期间系统上的某些其他进程使用了更多内存,则可以通过操作系统交换Redis内存。它会减少RSS(因为Redis内存的一部分不再存在于主内存中)。由此产生的碎裂率将小于1。
换句话说,只有当您确定操作系统没有换掉Redis内存时才会使用此比率(如果不是这样,那么无论如何都会出现性能问题。)
答案 1 :(得分:1)
除了交换之外,我知道两种使“内存碎片比率”小于1的方法:
具有一个Redis实例,该实例的数据很少或没有数据,但是有数千个空闲的客户端连接。从我的测试来看,redis似乎必须为每个客户端连接分配大约20 KB的内存,但是直到稍后,它的大部分才真正被使用(即不会出现在RSS中)。
具有一个主从设置,例如repl-backlog-size
为8 GB。复制开始后将立即分配8 GB的空间(仅在主版本为<4.0的主版本上,否则在主版本和从属版本上),但是仅在我们开始向主版本写入时才使用内存。因此,该比率最初将远远低于1,然后随着复制积压的填充而越来越接近1。