memcached
memcached概述
memcached是LiveJournal旗下Danga Interactive公司开发的一款软件。memcached是一个高性能,分布式内存对象缓存系统,具备通用性,
目的是用于为动态web程序加速,并减轻数据库的的负担。
mem->memory内存 + cached->缓存 = memcached
memcached安装详解
1.安装libevent
进入libevent官网 http://libevent.org/
现在的libevent最新的版本是2.0.20
wegt https://github.com/libevent/libevent/releases/download/release-2.0.22-stable/libevent-2.0.22-stable.tar.gz
tar -zxvf libevent-2.0.22-stable.tar.gz
cd libevent-2.0.22-stable
./configure
2.安装memcached
进入memcached官网 http://www.memcached.org/
可以看到现在memcached最新稳定版本是1.4.29
wegt http://www.memcached.org/files/memcached-1.4.29.tar.gz
tar -zxvf memcached-1.4.29.tar.gz
cd libevent-2.0.22-stable
./configure
memcached开启服务
输入 memcached -h 查看帮助
其中的主要参数
-p <num> 监听的TCP端口 (缺省: 11211)
-d 以守护进程方式运行Memcached
-u <username> 运行Memcached的账户,非root用户
-m <num> 最大的内存使用, 单位是MB,缺省是 64 MB
-c <num> 软连接数量, 缺省是 1024
-v 输出警告和错误信息
-vv 打印客户端的请求和返回信息
-h 打印帮助信息
-i 打印memcached和libevent的版权信息
使用一下命令开启memcached服务(内存大小为64M,端口使用11211)
memcached -d -m 32 -p 11211
memcached连接
使用命令 telnet 127.0.0.1 11211 其中第二个参数是IP地址,第三个参数是端口号
memcached命令
1.add 添加k-v缓存数据,该缓存不能存在。
add key flag expire length
key:键值
flag:标志 最开始是16位的无符号整数,现在的版本一般是32位。用户客户端存储自定义标记数据。
expire:有效期,单位为秒,0表示不过期(相对不过期,如果存储满了,还是有可能会被删除),如果设置为一分钟过期,则该参数设置为60。
还有一种就是设置过期Unix时间(从1970-1-1开始计算的秒数)。
length:缓存数据的长度
add name 0 0 5
lihua
STORED
其中STORED表示存储成功,还有一些响应命令
"STORED":表示存储成功。
"NOT_STORED":表示未存储,但并不是错误。如:对已经有的KEY使用add。
"EXISTS":表示使用cas命令设置数据未成功,在你最后一次获取数据后,数据已经被其它人修改。
"NOT_FOUND":表示使用cas存储数据时候,key不存储。
2.get 通过key取值
get key
get name
VALUE name 0 5
lihua
END
3.replace 更新一个k-v缓存,该缓存一定要存在。
replace key flag expire length
replace name 0 0 5
zhang
STORED
4.set 设置一个k-v缓存,set和add的区别在于:当key不存在时,set和add功能一样,都是新添数据,但是当key存在时,
set的功能又和replace一样,可以修改数据。
set key flag expire length
set gender 0 0 4
male
STORED
set name 0 0 6
liuxin
STORED
5.delete 删除一个k-v缓存
delete key [noreply]
noreply:可选参数。通知服务器不用发送应答消息。
delete name
DELETED
6.incr/decr 增值和减值操作
incr/decr <key> <value>
value:需要增大或者减小多小值。
add count 0 0 1
5
STORED
incr count 3
8
decr count 5
3
7.flush_all 清除所有的缓存数据。
8.stats 查询服务器的运行状态和其他内部数据。
memcached内存存储机制
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 8192slab class 2: chunk size 256 perslab 4096slab class 3: chunk size 512 perslab 2048slab class 4: chunk size 1024 perslab 1024slab class 5: chunk size 2048 perslab 512slab class 6: chunk size 4096 perslab 256slab class 7: chunk size 8192 perslab 128slab class 8: chunk size 16384 perslab 64slab class 9: chunk size 32768 perslab 32slab class 10: chunk size 65536 perslab 16slab class 11: chunk size 131072 perslab 8slab class 12: chunk size 262144 perslab 4slab class 13: chunk size 524288 perslab 2
可见,从128字节的组开始,组的大小依次增大为原来的2倍。 这样设置的问题是,slab之间的差别比较大,有些情况下就相当浪费内存。
因此,为尽量减少内存浪费,两年前追加了growth factor这个选项。
来看看现在的默认设置(f=1.25)时的输出(篇幅所限,这里只写到第10组):
slab class 1: chunk size 88 perslab 11915slab class 2: chunk size 112 perslab 9362slab class 3: chunk size 144 perslab 7281slab class 4: chunk size 184 perslab 5698slab class 5: chunk size 232 perslab 4519slab class 6: chunk size 296 perslab 3542slab class 7: chunk size 376 perslab 2788slab class 8: chunk size 472 perslab 2221slab class 9: chunk size 592 perslab 1771slab class 10: chunk size 744 perslab 1409
可见,组间差距比因子为2时小得多,更适合缓存几百字节的记录。 从上面的输出结果来看,可能会觉得有些计算误差, 这些误差是
为了保持字节数的对齐而故意设置的。
将memcached引入产品,或是直接使用默认值进行部署时, 最好是重新计算一下数据的预期平均长度,调整growth factor, 以获得最
恰当的设置。内存是珍贵的资源,浪费就太可惜了。
引用
http://kb.cnblogs.com/page/42732/
http://acooly.iteye.com/blog/1120346/
http://blog.csdn.net/ado1986/article/details/41927767