Memcached是一个高效的分布式内存cache,了解memcached的内存管理机制,便于我们理解memcached,让我们可以针对我们数据特点进行调优,让其更好的为我所用。这里简单谈一下我对memcached的内存管理的一些认识,在没有特别注明的情况下,这里谈到的memcached是1.2版本,1.1和1.2版本有一些差异。
基本概念:Slab和chunk
在Memcached内存结构中有两个非常重要的概念:slab 和 chunk,我们先从下图中对这两个概念有一个感性的认识:
![](https://p-blog.csdn.net/images/p_blog_csdn_net/Dato/bbf63173a8ef4c58a801012cd5f1e979.png)
图 1 memcached内存结构
Slab是一个内存块,它是memcached一次申请内存的最小单位。在启动memcached的时候一般会使用参数-m指定其可用内存,但是并不是在启动的那一刻所有的内存就全部分配出去了,只有在需要的时候才会去申请,而且每次申请一定是一个slab。Slab的大小固定为1M(1048576 Byte),一个slab由若干个大小相等的chunk组成。每个chunk中都保存了一个item结构体、一对key和value。
虽然在同一个slab中chunk的大小相等的,但是在不同的slab中chunk的大小并不一定相等,在memcached中按照chunk的大小不同,可以把slab分为很多种类(class)。在启动memcached的时候可以通过-vv来查看slab的种类:
![](https://p-blog.csdn.net/images/p_blog_csdn_net/Dato/96ef0d7287164d8e9b6c7a5ba817dba7.png)
图2 slab分组信息
从上图可以看到,默认情况下memcached把slab分为40类(class1~class40),在class 1中,chunk的大小为80字节,由于一个slab的大小是固定的1048576字节(1M),因此在class1中最多可以有13107个chunk:
13107×80 + 16 = 1048576
在class1中,剩余的16字节因为不够一个chunk的大小(80byte),因此会被浪费掉。每类chunk的大小有一定的计算公式的,假定i代表分类,class i的计算公式如下:
chunk size(class i) : (default_size+item_size)*f^(i-1)+
CHUNK_ALIGN_BYTES
-
default_size: 默认大小为48字节,也就是memcached默认的key+value的大小为48字节,可以通过-n参数来调节其大小;
-
item_size: item结构体的长度,固定为32字节。default_size大小为48字节,item_size为32,因此class1的chunk大小为48+32=80字节;
-
f为factor,是chunk变化大小的因素,默认值为1.25,调节f可以影响chunk的步进大小,在启动时可以使用-f来指定;
-
CHUNK_ALIGN_BYTES是一个修正值,用来保证chunk的大小是某个值的整数倍(在32位机器上要求chunk的大小是4的整数倍)。
从上面的分析可以看到,我们实际可以调节的参数有-f、-n,在memcached的实际运行中,我们还需要观察我们的数据特征,合理的调节f,n的值,使我们的内存得到充分的利用减少浪费。
内存申请分配
Memcached内存管理采取预分配、分组管理的方式,分组管理就是我们上面提到的slab class,按照chunk的大小slab被分为很多种类。下面解释一下memcached的内存预分配过程。
向memcached添加一个item时候,memcached首先会根据item的大小,来选择最合适的slab class:例如item的大小为190字节,默认情况下class 4的chunk大小为160字节显然不合适,class 5的chunk大小为200字节,大于190字节,因此该item将放在class 5中(显然这里会有10字节的浪费是不可避免的),计算好所要放入的chunk之后,memcached会去检查该类大小的chunk还有没有空闲的,如果没有,将会申请1M(1个slab)的空间并划分为该种类chunk。例如我们第一次向memcached中放入一个190字节的item时,memcached会产生一个slab class 2(也叫一个page),并会用去一个chunk,剩余5241个chunk供下次有适合大小item时使用,当我们用完这所有的5242个chunk之后,下次再有一个在160~200字节之间的item添加进来时,memcached会再次产生一个class 5的slab(这样就存在了2个pages)。查看slab的使用情况,我们可以telnet ip port,然后输入命令 stats slabs即可:
例如:telnet 10.0.4.210 11211
stats slabs
STAT 5:chunk_size 200
STAT 5:chunks_per_page 5242
STAT 5:total_pages 1
STAT 5:total_chunks 5242
STAT 5:used_chunks 5242
STAT 5:free_chunks 0
STAT 5:free_chunks_end 5241
STAT active_slabs 1
STAT total_malloced 1048400
|
图3 stats slab
图3显示的是第一次放入一个190字节的item之后的统计结果。