> Linux集群 > 服务器集群 >

memcached的内存存储


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

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

 

下面来看看Slab Allocator的原理

 

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

 

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

slab allocator还有重复使用已分配的内存的目的。也就是说,分配到的内存不会释放,而是重复利用。如图:

点击查看原图

 

Page

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

Chunk

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

Slab Class

特定大小的chunk的组。

 

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

 

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

点击查看原图

 

Slab Allocator的缺点

 

Slab Allocator解决了当初的内存碎片问题,但新的机制也给memcached带来了新的问题。由于分配的是特定长度的内存,因此无法有效利用分配的内存。例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了。如图:

点击查看原图

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

 

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

 

使用Growth Factor进行调优

 

memcached在启动时指定Growth Factor因子(通过f

选项),就可以在某种程度上控制slab之间的

差异。默认值为1.25。但是,在该选项出现之前,这个因子曾经固定为2,称为“powers of 2”策略。

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

点击查看原图

 

可见,从128字节的组开始,组的大小依次增大为原来的2倍。 这样设置的问题是,slab之间的差别比较大,有些情况下就相当浪费内存。 因此,为尽量减少内存浪费,两年前追加了growth factor这个选项。

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

点击查看原图

 

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

将memcached引入产品,或是直接使用默认值进行部署时,最好是重新计算一下数据的预期平均长度,调整growth factor,以获得最恰当的设置。内存是珍贵的资源,浪费就太可惜了。

 

查看memcached的内部状态:stats命令

 

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

 

[root@211308 ~]# telnet localhost 11211

Trying 184.22.240.34...

Connected to localhost.

Escape character is '^]'.

stats

STAT pid 8007

STAT uptime 120

STAT time 1313818720

STAT version 1.4.7

STAT libevent 1.4.13-stable

STAT pointer_size 64

STAT rusage_user 0.002999

STAT rusage_system 0.001999

STAT curr_connections 10

STAT total_connections 12

STAT connection_structures 11

STAT cmd_get 0

STAT cmd_set 0

STAT cmd_flush 0

STAT get_hits 0

STAT get_misses 0

STAT delete_misses 0

STAT delete_hits 0

STAT incr_misses 0

STAT incr_hits 0

STAT decr_misses 0

STAT decr_hits 0

STAT cas_misses 0

STAT cas_hits 0

STAT cas_badval 0

STAT auth_cmds 0

STAT auth_errors 0

STAT bytes_read 135

STAT bytes_written 105

STAT limit_maxbytes 67108864

STAT accepting_conns 1

STAT listen_disabled_num 0

STAT threads 4

STAT conn_yields 0

STAT bytes 0

STAT curr_items 0

STAT total_items 0

STAT evictions 0

STAT reclaimed 0

END

 

查看slabs的使用状况

 

使用memcached的创造着Brad写的名为memcachedtool的Perl脚本,可以方便地获得slab的使用情况(它将memcached的返回值整理成容易阅读的格式)。可以从下面的地址获得脚本:

    • http://code.sixapart.com/svn/memcached/trunk/server/scripts/memcached-tool

 点击查看原图

 

获得的信息如下所示:

# Item_Size Max_age 1MB_pages Count Full?

1 104 B 1394292 s 1215 12249628 yes

2 136 B 1456795 s 52 400919 yes

3 176 B 1339587 s 33 196567 yes

4 224 B 1360926 s 109 510221 yes

5 280 B 1570071 s 49 183452 yes

6 352 B 1592051 s 77 229197 yes

7 440 B 1517732 s 66 157183 yes

8 552 B 1460821 s 62 117697 yes

9 696 B 1521917 s 143 215308 yes

10 872 B 1695035 s 205 246162 yes

11 1.1 kB 1681650 s 233 221968 yes

12 1.3 kB 1603363 s 241 183621 yes

13 1.7 kB 1634218 s 94 57197 yes

14 2.1 kB 1695038 s 75 36488 yes

15 2.6 kB 1747075 s 65 25203 yes

16 3.3 kB 1760661 s 78 24167 yes

 

 

列含义

# slab class编号

Item_Size Chunk大小

Max_age LRU内最旧的记录的生存时间

1MB_pages 分配给Slab的页数

Count Slab内的记录数

Full? Slab内是否含有空闲chunk

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

 

总结

 

本次简单说明了memcached的缓存机制和调优方法。希望读者能理解memcached的内存管理原理及其优缺点。




(责任编辑:IT)