Memcached基础
What is Memcached ?
Free & open source, high-performance, distributed memory object caching system
一个开源,免费的高性能,分布式内存缓存系统。
在我们的应用程序中,一般会将数据库的一些经常需要查询用到的数据缓存至Memcached,以提高动态Web应用的响应速度。如下图所示:
<a href="http://s3.51cto.com/wyfs02/M00/58/00/wKiom1SmQaGTfoRKAAE4oHmqY6s517.jpg" target="_blank"></a>
快速体验Memcached
【关于libevent的简要说明:libevent就是一个程序库,他将Linux的epoll、BSD系统的kqueue等事件处理机制封装成统一的接口,即使对服务器的连接增加,也能发挥0(1)的性能。Memcached使用这个库,可以在Linux平台上发挥其高性能。】
过程如下:
1
2
3
4
5
6
7
8
9
<code>tar</code> <code>-xf libevent-2.0.20-stable.</code><code>tar</code><code>.gz</code>
<code>cd</code> <code>libevent-2.0.20-stable</code>
<code>.</code><code>/configure</code> <code>--prefix=</code><code>/usr/local/libevent</code>
<code>make</code>
<code>make</code> <code>install</code>
<code>tar</code> <code>-xf memcached-1.4.22.</code><code>tar</code><code>.gz</code>
<code>cd</code> <code>memcached-1.4.22</code>
<code>.</code><code>/configure</code> <code>--prefix=</code><code>/usr/local/memached</code> <code>--with-libevent=</code><code>/usr/local/libevent/</code>
<code>make</code> <code>&& </code><code>make</code> <code>install</code>
启动Memcached
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<code>[root@www bin]</code><code># ./memcached -p 11211 -m 64 -f 1.5 -u nobody -vvv -d</code>
<code>slab class 1: chunk size 80 perslab 13107</code>
<code>slab class 2: chunk size 120 perslab 8738</code>
<code>slab class 3: chunk size 184 perslab 5698</code>
<code>slab class 4: chunk size 280 perslab 3744</code>
<code>slab class 5: chunk size 424 perslab 2473</code>
<code>slab class 6: chunk size 640 perslab 1638</code>
<code>slab class 7: chunk size 960 perslab 1092</code>
<code>slab class 8: chunk size 1440 perslab 728</code>
<code>slab class 9: chunk size 2160 perslab 485</code>
<code>slab class 10: chunk size 3240 perslab 323</code>
<code>slab class 11: chunk size 4864 perslab 215</code>
<code>slab class 12: chunk size 7296 perslab 143</code>
<code>slab class 13: chunk size 10944 perslab 95</code>
<code>slab class 14: chunk size 16416 perslab 63</code>
<code>slab class 15: chunk size 24624 perslab 42</code>
<code>slab class 16: chunk size 36936 perslab 28</code>
<code>slab class 17: chunk size 55408 perslab 18</code>
<code>slab class 18: chunk size 83112 perslab 12</code>
<code>slab class 19: chunk size 124672 perslab 8</code>
<code>slab class 20: chunk size 187008 perslab 5</code>
<code>slab class 21: chunk size 280512 perslab 3</code>
<code>slab class 22: chunk size 420768 perslab 2</code>
<code>slab class 23: chunk size 631152 perslab 1</code>
<code>slab class 24: chunk size 1048576 perslab 1</code>
可以利用./memcached -h的方式来了解一些选项的作用:
-p <num> TCP port number to listen on (default: 11211) 指定端口
-l <addr> interface to listen on (default: INADDR_ANY, all addresses)
监听地址,想一想,如果我们的机器上有多个网卡我们监听在哪个网卡上呢?
-d run as a daemon 表示以一个后台服务的方式运行
-u <username> assume identity of <username> (only when run as root)
以哪个用户的身份运行
-m <num> max memory to use for items in megabytes (default: 64 MB)
以M为单位指定最大的内存空间
-f <factor> chunk size growth factor (default: 1.25)
指定增长因子
-n <bytes> minimum space allocated for key+value+flags (default: 48)
最小存储单位。实际上,这里指定的是最小的slab chunk大小
在上面启动过程中,我们使用了-vvv的方式输出了启动过程的详细信息,那么slab class , chunk这些是什么呢?增长因子又是干什么的?
端口验证:
<code>[root@www ~]</code><code># netstat -tnlp | grep 11211</code>
<code>tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN 3292</code><code>/memcached</code>
<code>tcp 0 0 :::11211 :::* LISTEN 3292</code><code>/memcached</code>
Memcached启动后,我们怎么连接进行操作呢?
要知道Memcached是基于Client/Server架构的,上面的是启动Server端,表示Memcached已经有64M内存空间来进行缓存数据管理。至于设置哪些缓存数据,数据有效期是多少等这些都是客户端的事情。很多语言都实现了Memcached客户端,比如Java/PHP等。需要注意的是,Memcached的一个重要特征--协议简单。比如,我们就可以使用telnet来操作Memcached:
<code>[root@www ~]</code><code># telnet 192.168.204.88 11211</code>
<code>Trying 192.168.204.88...</code>
<code>Connected to www.zfz2.com (192.168.204.88).</code>
<code>Escape character is </code><code>'^]'</code><code>.</code>
<code>stats</code>
stats命令可以获取到Memcached运行时相关信息。
一些常用命令:
add命令 添加新键
add keyname flag timeout datasize
<code>add name 0 30 5</code>
<code>hello</code>
<code>STORED</code>
get命令 取得键值
get keyname
<code>get name</code>
<code>VALUE name 0 5</code>
<code>END</code>
set 无条件设置一个键
说白了,就是有键则覆盖,无键则添加。
set keyname flag timeout datasize
replace 替换已经存在的KEY
replace keyname flag timeout datasize
append keyname flag timeout append_datasize
prepend keyname flag timeout prepend_datasize
<code>add name 0 60 5</code>
<code>append name 0 60 2</code>
<code>aa</code>
<code>VALUE name 0 7</code>
<code>helloaa</code>
incr keyname increments 对键值增长
decr keyname decrements 对键值减少
<code>add score 0 120 1</code>
<code>1</code>
<code>incr score 2</code>
<code>3</code>
<code>get score</code>
<code>VALUE score 0 1</code>
delete keyname 删除指定键
flush_all 清理所有键
stats 状态信息
quit 表示退出
version 查看版本
Memcached的内存存储和删除机制
Memcached是一个缓存服务器,并且它认为自己缓存的数据并不是关键性数据,也就是如果Memcached重启,缓存数据会丢失,需要重新建立。Memcached对高可用的支持不是很好,但是对分布式提供了很好的支持。下面我们来分析下Memcached的内存存储机制:
Memcached的内存存储机制采用了Slab Allocator的方式,按照预先规定的大小,将分配的内存分割成特定长度的块,以减少内存碎片问题。Slab Allocator可以重复使用以分配的内存。如下图所示:
<a href="http://s3.51cto.com/wyfs02/M00/58/00/wKioL1SnTinAkEbvAAFO-dwM2f8650.jpg" target="_blank"></a>
有多个Slab Class类别,每一个Slab Class里面有多个相同大小的Chunk,而Chunk就是Memcached存储数据的最小单元。当Memcached接受到数据需要缓存时,会选择最适合数据大小的Slab,然后从Slab中选择空闲的Chunk进行存储。当然这种方式是无法避免内存浪费的。
在启动Memcached时,我们指定了-f选项,其实是在指定Slab中Chunk大小的增长因子,这是Memcached为我们提供的一个可以进行调优的选项。我们可以根据客户端缓存数据的大小,做一个预估,通过增长因子来调整Slab的差别,以获得最恰当的设置。
在Memcached中缓存数据的时候,我们可以指定数据的失效期,可以指定到秒。那么如果时间到了,Memcached会怎么做呢?
Memcached并不会释放已经分配的内存,超时后,客户端就无法在看到该记录了。Memcached的删除机制思想如下:
LAZY机制
Memcached内部不会去监控记录是否过期,而是在get的时候去判断一下时间戳,这样就知道是不是过期了。这样的话,Memcached因为LAZY的机制不会在这个方面去占用CPU。
LRU算法
最近最少使用原理,当Memcached空间不足时,要清理,怎么清理呢?就是清理那些最近未被使用的记录的空间,将这些空间重新分配给新的记录。
Memcached的分布式机制与一致性哈希算法
当我们使用多台Memcached来缓存数据时,就利用到了Memcached的分布式。Memcached的分布式的最大特点是不相互通信。在分布式的情况下,当我们要保存一个键时,可以简单的根据键计算一个值,从而决定存储至哪个Memcached中,当要get这个键的时候,利用同样的方式到对应的Memcached服务器中去取。比如,我们有10台Memcached(编号0-9),现在要保存一个key,通过对key进行计算,比如取得它的HASH值,然后对10取余,假设得到8,我们就将这个KEY存储至编号为8的服务器中。这样的话,虽然算法上简单,存取上实现了分布式,但是有一个明显的缺点,就是如果增加或者减少了Memcached的节点个数,我们的大部分缓存就失效了,需要重新建立了。【原因在于取余的结果发生了巨变】那么有没有一种方式,当我们增加或者减少Memcached节点个数时,带来的影响最小呢?
关于一致性HASH算法(Consistent Hashing)
<a href="http://s3.51cto.com/wyfs02/M01/58/03/wKiom1SnVK6A-pyRAAFR1OdEa2U133.jpg" target="_blank"></a>
基本原理说明:
有一个HASH环,分布着2的32次方个点,然后求出各个Memcached服务器的HASH值,将其置于环上的各个点上。用相同的方式计算需要保存的数据的键的HASH值,并映射到环上的位置,从映射处开始顺时针开始查找最近的Memcached,找到后就保存至这个服务器。如果要取得数据,也采用相同的方式定位服务器。
这种算法就是一致性HASH算法,通过这样可以在添加、删除服务器时,最大限度的抑制键的重新分布。
本文转自zfz_linux_boy 51CTO博客,原文链接:http://blog.51cto.com/zhangfengzhe/1598626,如需转载请自行联系原作者