[Memcached]理解 Memcached 的内存存储

        本文部分内容转载自memcached全面剖析–2. 理解memcached的内存存储 ,仅供学习使用。

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

        最近的 Memcached 默认情况下采用了名为 Slab Allocation 的机制分配、管理内存。在该机制出现以前,内存的分配是通过对所有记录简单地进行 malloc 和 free 来进行的。但是,这种方式会导致内存碎片,加重操作系统内存管理区的负担,最坏的情况下,会导致操作系统比 Memcached 进程本身还慢。Slab Allocation 就是为解决该问题而诞生的。

        下面来看看 Slab Allocation 的原理。下面是 Memcached 文档中的 Slab Allocation 的目标:

        the primary goal of the slabs subsystem in memcached was to eliminate memory fragmentation issues totally by using fixed-size memory chunks coming from a few predetermined size classes.

        也就是说,Slab Allocation 的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,已完全解决内存碎片问题。

        Slab Allocation 的原理相当简单。将分配的内存分割成各种尺寸的块(chunk),并把尺寸相同的块分成组(chunk 的集合)。

[Memcached]理解 Memcached 的内存存储_第1张图片

Slab Allocation 的构造图

        而且,Slab Allocation 还有重复使用已分配的内存的目的。也就是说,分配到的内存不会释放,而是重复利用。

Slab Allocation 的主要术语

        Page

        分配给 Slab 的内存空间,默认是 1MB。分配给 Slab 之后根据 Slab 的大小切分成 Chunk。

        Chunk

        用于缓存记录的内存空间。

        Slab Class

        特定大小的 Chunk 的组。

在 Slab 中缓存记录的原理

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

        Memcached 根据收到的数据的大小,选择最适合数据大小的 Slab。Memcached 中保存着 Slab 内空闲 Chunk 的列表,根据该列表选择 Chunk,然后将数据缓存于其中。

[Memcached]理解 Memcached 的内存存储_第2张图片

选择存储记录的组的方法

        实际上,Slab Allocation 是有利也有弊。下面介绍一下它的缺点。

Slab Allocation 的缺点

        Slab Allocation 解决了当初的内存碎片问题,但新的机制也给 Memcached 带来了新的问题。

        这个问题就是,由于分配的是特定长度的内存,因此无法有效利用分配的内存。例如,将 100 字节的数据缓存到 128 字节的 Chunk 中,剩余的 28 字节就浪费了。

[Memcached]理解 Memcached 的内存存储_第3张图片

Chunk 空间的使用

        对于该问题目前还没有完美的解决方案,但在文档中记载了比较有效的解决方案。

        The most efficient way to reduce the waste is to use a list of size classes that closely matches (if that's at all possible) common sizes of objects that the clients of this particular installation of memcached are likely to store.

        就是说,如果预先知道客户端发送的数据的公用大小,或者仅缓存大小相同的数据的情况下,只要使用适合数据大小的组的列表,就可以减少浪费。

        但是很遗憾,现在还不能进行任何调优,只能期待以后的版本了。但是,我们可以调节 Slab Class 的大小的差别。

使用 Growth Factor 进行调优

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

        让我们用以前的设置,以 verbose 模式启动 Memcached 试试看:

$ memcached -f 2 -vv

        下面是启动后的 verbose 输出:

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,以获得最恰当的设置。内存是珍贵的资源,浪费就太可惜了。

        接下来介绍一下如何使用 Memcached 的 stats 命令查看 Slabs 的利用率等各种各样的信息。

查看 Memcached 的内部状态

        Memcached 有个名为 stats 的命令,使用它可以获得各种各样的信息。执行命令的方法很多,用 telnet 最为简单:

$ telnet 主机名 端口号

        连接到 Memcached 之后,输入 stats 再按回车,即可获得包括资源利用率在内的各种信息。此外,输入“stats slabs”或“stats items”还可以获得关于缓存记录的信息。结束程序请输入 quit。

        这些命令的详细信息可以参考 Memcached 软件包内的 protocol.txt 文档。

        另外,如果安装了 libmemcached 这个面向 C/C++ 语言的客户端库,就会安装 memstat 这个命令。

查看 Slabs 的使用情况

        使用 Memcached 的创造者 Brad 写的名为 memcached-tool 的 Perl 脚本,可以方便得获得 Slab 的使用情况(它将 Memcached 的返回值整理成容易阅读的格式)。使用方法也极其简单:

$ memcached-tool 主机名:端口 选项

        查看 Slabs 使用状况时无需指定选项,因此用下面的命令即可。

$ memcached-tool 主机名:端口

        获得的信息中各列的含义如下:

含义
# Slab Class 编号
Item_Size Chunk 大小
Max_age LRU 内最旧的记录的生存时间
1MB_pages 分配给 Slab 的页数
Count Slab 内的记录数
Full? Slab 内是否含有空闲 Chunk

        从这个脚本获得的信息对于调优非常方便,强烈推荐使用。

你可能感兴趣的:(Memcached)