内存存储

1、Slab Allocation机制:整理内存以便重复使用

Memcached默认情况下采用了名为Slab Allocator的机制分配、管理内存。
Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,以完全解决内存碎片问题。
如下图:

图例说明:
Slab Allocation的原理相当简单。 将分配的内存分割成各种尺寸的块(chunk),并把尺寸相同的块分成组(chunk的集合)。而且,slab allocator还有重复使用已分配的内存的目的。也就是说,分配到的内存不会释放,而是重复利用。

2、Slab Allocation的主要术语

Page
分配给Slab的内存空间,默认是1MB。分配给Slab之后根据slab的大小切分成chunk。
Chunk
用于缓存记录的内存空间。
Slab Class
特定大小的chunk的组。

3、在Slab中缓存记录的原理

下面说明memcached如何针对客户端发送的数据选择slab并缓存到chunk中。

图例说明:
memcached根据收到的数据的大小,选择最适合数据大小的slab。
memcached中保存着slab内空闲chunk的列表,根据该列表选择chunk,然后将数据缓存于其中。

4、Slab Allocator的缺点

缺点:
由于分配的是特定长度的内存,因此无法有效利用分配的内存。

图例说明:
将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了。
文档解决方案:
如果预先知道客户端发送的数据的公用大小,或者仅缓存大小相同的数据的情况下,只要使用适合数据大小的组的列表,就可以减少浪费。
但是,现在还不能进行任何调优。

5、使用Growth Factor进行调优

Memcached在启动时指定Growth Factor因子(通过f 选项),就可以在某种程度上控制slab之间的差异。默认值为1.25。
但是,在该选项出现之前,这个因子曾经固定为2,称为“powers of 2”策略。
powers of 2策略查看:

$ memcached -f 2 -vv

结果如下:

slab class 1: chunk size 128 perslab 8192
slab class 2: chunk size 256 perslab 4096
slab class 3: chunk size 512 perslab 2048
slab class 4: chunk size 1024 perslab 1024
slab class 5: chunk size 2048 perslab 512
slab class 6: chunk size 4096 perslab 256
slab class 7: chunk size 8192 perslab 128
slab class 8: chunk size 16384 perslab 64
slab class 9: chunk size 32768 perslab 32
slab class 10: chunk size 65536 perslab 16
slab class 11: chunk size 131072 perslab 8
slab class 12: chunk size 262144 perslab 4
slab class 13: chunk size 524288 perslab 2

从上面可以看出,从128字节的组开始,组的大小依次增大为原来的2倍。这样slab之间的差别比较大,内存比较浪费。

growth factor来看现在的默认设置(f=1.25)时的输出

slab class 1: chunk size 88 perslab 11915
slab class 2: chunk size 112 perslab 9362
slab class 3: chunk size 144 perslab 7281
slab class 4: chunk size 184 perslab 5698
slab class 5: chunk size 232 perslab 4519
slab class 6: chunk size 296 perslab 3542
slab class 7: chunk size 376 perslab 2788
slab class 8: chunk size 472 perslab 2221
slab class 9: chunk size 592 perslab 1771
slab class 10: chunk size 744 perslab 1409

从上面可以看出,组间差距比因子为2时小得多,更适合缓存几百字节的记录。而且仔细看可能会觉得有些计算误差,这些误差是为了保持字节数的对齐故意设置的。

建议调优方案
在Memcached引入产品,或直接使用默认值进行部署时,最好从新计算一下预期平均长度,调整growth factor,以获得最恰当的设置。