Slab Allocation机制:整理内存以便重复使用
最近的memcached默认情况下采用了名为Slab
Allocator的机制分配、管理内存。在该机制出现以前,内存的分配是通过对所有记录简单地进行malloc和free来进行的。但是,这种方式会导致内存碎片,加重操作系统内存管理器的负担,最坏的情况下,会导致操作系统比memcached进程本身还慢。Slab
Allocator就是为解决该问题而诞生的。
下面来看看Slab Allocator的原理。下面是memcached文档中的slab allocator的目标:
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 Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,以完全解决内存碎片问题。
Slab Allocation的原理相当简单。 将分配的内存分割成各种尺寸的块(chunk),并把尺寸相同的块分成组(chunk的集合)(图1)。
图1 Slab Allocation的构造图
而且,slab allocator还有重复使用已分配的内存的目的。也就是说,分配到的内存不会释放,而是重复利用。
Slab Allocation的主要术语
Page
分配给Slab的内存空间,默认是1MB。分配给Slab之后根据slab的大小切分成chunk。
Chunk
用于缓存记录的内存空间。
Slab Class
特定大小的chunk的组。
在Slab中缓存记录的原理
下面说明memcached如何针对客户端发送的数据选择slab并缓存到chunk中。
memcached根据收到的数据的大小,选择最适合数据大小的slab(图2)。
memcached中保存着slab内空闲chunk的列表,根据该列表选择chunk,然后将数据缓存于其中。
图2 选择存储记录的组的方法
实际上,Slab Allocator也是有利也有弊。下面介绍一下它的缺点。
Slab Allocator的缺点
Slab Allocator解决了当初的内存碎片问题,但新的机制也给memcached带来了新的问题。
这个问题就是,由于分配的是特定长度的内存,因此无法有效利用分配的内存。例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了(图3)。
图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选项。
使用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)时的输出(篇幅所限,这里只写到第10组):
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文档。
$ telnet localhost 11211
Trying ::1...
Connected to localhost.
Escape character is '^]'.
stats
STAT pid 481
STAT uptime 16574
STAT time 1213687612
STAT version 1.2.5
STAT pointer_size 32
STAT rusage_user 0.102297
STAT rusage_system 0.214317
STAT curr_items 0
STAT total_items 0
STAT bytes 0
STAT curr_connections 6
STAT total_connections 8
STAT connection_structures 7
STAT cmd_get 0
STAT cmd_set 0
STAT get_hits 0
STAT get_misses 0
STAT evictions 0
STAT bytes_read 20
STAT bytes_written 465
STAT limit_maxbytes 67108864
STAT threads 4
END
quit
另外,如果安装了libmemcached这个面向C/C++语言的客户端库,就会安装 memstat
这个命令。使用方法很简单,可以用更少的步骤获得与telnet相同的信息,还能一次性从多台服务器获得信息。
$ memstat --servers=server1,server2,server3,...
libmemcached可以从下面的地址获得:
查看slabs的使用状况
使用memcached的创造着Brad写的名为memcached-tool的Perl脚本,可以方便地获得slab的使用情况(它将memcached的返回值整理成容易阅读的格式)。可以从下面的地址获得脚本:
使用方法也极其简单:
$ memcached-tool 主机名:端口 选项
查看slabs使用状况时无需指定选项,因此用下面的命令即可:
$ 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的内存管理原理及其优缺点。
下次将继续说明LRU和Expire等原理,以及memcached的最新发展方向—— 可扩充体系(pluggable architecher))。
分享到:
相关推荐
04-memcached内存分配机制.wmv
Memcached内存分配与SLAB机制,详细解读
Memcached内存分配与SLAB机制[借鉴].pdf
良好的内存分配机制,对于大型的经常反问内存的系统,提高其访问效率,有很大的帮助。同时也是我们学习的好参考
主要讲述的是Memcached的缓存机制、内存分配和适用条件等; 并不包括如何下载安装、适用维护和具体的参数设置等这些东东; 还请仔细甄别,莫做无谓下载,呵呵
最近的memcached默认情况下采用了名为SlabAllocator的机制分配、管理内存。 在该机制出现以前,内存的分配是通过对所有记录简单地进行malloc和free来进行的。但是,这种方式会导致内存碎片,加重操作系统内存管理器...
《Memcached内存分析、调优、集群.pptx》 《NET版分布式缓存Memcached测试实例.docx》 《Memcached管理及_.NET_开发.doc》 《memcached-win32-1.4.4-14.zip》 《安装Memcached及Memcached配置.doc》 《Linux...
ydx_slab_util实现一个内存池,内存管理机制借鉴memcached,使用一系列链表管理不同大小的内存区块。memcached一次分配(默认64M)固定大小的内存区域,使用完毕后使用LRU淘汰最早不使用的内存段。作为一个通用内存池...
现在一些.NET开发人员开始放弃ASP.NET内置的缓存机制,转而使用Memcached——一种分布式的内存缓存系统。当运行在单独的Web服务器上,你可以很容易地清除一个已经确认被改变了的缓存。可惜,ASP.NET没有一个很好的...
memcached是缓存,所以数据不会永久保存在...上次介绍过,memcached不会释放已分配的内存。记录超时后,客户端就无法再看见该记录(invisible,透明), 其存储空间即可重复使用。memcached内部不会监视记录是否过
由于它的工作机制是在内存中开辟一块空间,然后建立一个HashTable,Memcached自管理这 些HashTable。 Memcached又是什么? Memcached是Memcache系统的主程序文件,以守护程序方式运行于一个或多个服务器中,随时...
Memcache使用了Slab Allocator的内存分配机制:按照预先规定的大小,将分配的内存分割成特定长度的块,以完全解决内存碎片问题 Memcache的存储涉及到slab,page,chunk三个概念 1.Chunk为固定大小的内存空间,...
掌握JVM内存分配、JVM垃圾回收;类装载机制; 性能优化; 反射机制;多线程;IO/NIO; 网络编程;常用数据结构和相关算法。 2、对面向对象的软件开发思想有清晰的认识、熟悉掌握常用的设计模式;设计模式;单例模式...
将 libmemcached 的内存分配器改成了易语言统一申请内存的方式。 修复了URI解析过程的一个逻辑陷阱。兼容中文等情况的URI二次解析可能出现的问题。 修复了XML解析等情况下得到的文本内容超出预计范围的问题。 修复了...
4 内存分配 4 缓存策略 4 缓存数据库查询 4 数据冗余与故障预防 4 Memcached客户端(mc) 4 缓存式的Web应用程序架构 4 性能测试 4 dbcached 4 Memcached 和 dbcached 在功能上一样吗? 4 列存系列 4 Hadoop之Hbase 4...
│ 第62节:内存分配的Chunk、Slab演示.avi │ 第63节:Memcached的Java客户端开发.avi │ 第64节:理解Memcached的分布式方式.avi │ 第65节:Memcached内存调优.avi │ 第66节:Memcached的限制和使用建议.avi │ ...
将 libmemcached 的内存分配器改成了易语言统一申请内存的方式。 修复了URI解析过程的一个逻辑陷阱。兼容中文等情况的URI二次解析可能出现的问题。 修复了XML解析等情况下得到的文本内容超出预计范围的问题。 修复了...
GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....