Memcached是一款开源、高性能、分布式内存对象缓存系统,可应用各种需要缓存的场景,其主要目的是通过降低对Database的访问来加速web应用程序。它是一个基于内存的“键值对”存储,用于存储数据库调用、API调用或页面引用结果的直接数据,如字符串、对象等。
Memcached现已成为mixi、hatena、Facebook、Vox、LiveJournal等众多服务中提高Web应用扩展性的重要因素。
Memcached有以特点
1. 简单key/value存储:服务器不关心数据本身的意义及结构,只要是可序列化数据即可。存储项由“键、过期时间、可选的标志及数据”四个部分组成;
2. 功能的实现一半依赖于客户端,一半基于服务器端:客户负责发送存储项至服务器端、从服务端获取数据以及无法连接至服务器时采用相应的动作;服务端负责接收、存储数据,并负责数据项的超时过期;
3. 各服务器间彼此无视:不在服务器间进行数据同步;
4. O(1)的执行效率
5. 清理超期数据:默认情况下,Memcached工作在Lazy模式下,是一个LRU(最近最少使用)缓存,同时,它按事先预订的时长清理超期数据;但事实上,memcached不会删除任何已缓存数据,只是在其过期之后不再为客户所见;而且,memcached也不会真正按期限清理缓存,而仅是当get命令到达时检查其时长;但是键一旦过期,则再次查询不会返回结果
Memcached虽然是一个键值存储server,但是它本身无法决定缓存那些数据,而是由客户端决定的键名,键值,缓存时长,标志位等
Memcached可以基于文本或者二进制上传和下载数据
Memcached将所有数据缓存再自己的内存中,并不会进行持久存储,且它认为自己也仅仅是一个缓存server,其上的数据丢失并不影响原数据,仅仅对服务有所影响
不同的memcached服务器之间不能进行通信,也不监控对方心跳信息,client端可以根据调度器如Nginx、haproxy、lvs等基于持久连接将数据缓存在多台memcached上(为了能够保证始终能够在同一个memcached找到同一个键,就需要对键做哈希运算,如将键做一定运算后/memcached的个数,再取余,根据余数将其存储在固定memcached服务器上,这样只要知道键一计算,就可以知道它在哪个server上存着;但这个取余法有个致命缺陷就是,万一挂掉或多了一个memcached服务器,其同一个键取余结果就会改变,就再也不能根据原来计算方法找到其对应的键值,即所有memcached上的缓存都失效)
这时就可以使用一致性哈希运算:1到2^32之间取几个对应区间对应每台服务器,然后对键/2^32取余,然后根据余数顺时针找最近服务器进行缓存,这样一旦挂了或加了一个memcached其结果也只让一台服务器上的缓存失效
Memcached有两个很重要组件:
1:buddy system(伙伴系统)为了保证内存中的空间连续可用buddy system会将临近的空间碎片合并为一个大的连续空间,避免了内存碎片的产生
2:slab allocator:当要存储小于内存页面大小(4K)数据时如存储一个128字节的数据,为了节省空间,slab allocator会将一个4K的内存页提前划分为许多128字节的块,将其存在里面,然后标记此块已近使用,而数据释放后也不会销毁这个128字节的块,会提供给以后的数据存储使用。并且slab allocator slab为不同大小的数据结构提前准备各种不同大小的内存块,存储时选择与它大小最近,且比它大的块进行存储,这样就提高了内存的利用效率
memcached依赖于libevent API,因此要事先安装之,项目主页:,且memcached是基于Event_Driven(事件驱动)的I/O机制,而event_driven是由libevent这个库提供的
[root@node1 libevent-2.0.22-stable]# ./configure --prefix=/usr/local/libevent
[root@node1 libevent-2.0.22-stable]# make && make install
[root@node1 local]# echo "/usr/local/libevent/lib/" > /etc/ld.so.conf.d/libevent.conf
[root@node1 local]# ldconfig -v
[root@node1 ~]# yum install -y cyrus-sasl-devel
装memcached的服务端memcached memcached官网,org
[root@node1 tool]# tar memcached-1.4.33.tar.gz
[root@node1 tool]# cd memcached-1.4.33
[root@node1 memcached-1.4.33]# ./configure --enable-sasl --prefix=/usr/local/memcached --with-libevent=/usr/local/libevent
[root@node1 memcached-1.4.33]# make && make install
-l <ip_addr>:指定进程监听的地址;
-d: 以服务模式运行;
-u <username>:以指定的用户身份运行memcached进程;
-m <num>:用于缓存数据的最大内存空间,单位为MB,默认为64MB;
-c <num>:最大支持的并发连接数,默认为1024;
-p <num>: 指定监听的TCP端口,默认为11211;
-U <num>:指定监听的UDP端口,默认为11211,0表示关闭UDP端口;
-t <threads>:用于处理入站请求的最大线程数,仅在memcached编译时开启了支持线程才有效;
-f <num>:设定Slab Allocator定义预先分配内存空间大小固定的块时使用的增长因子;
-M:当内存空间不够使用时返回错误信息,而不是按LRU算法利用空间;
-n: 指定最小的slab chunk大小;单位是字节;
-S: 启用sasl进行用户认证;
建立一个内存空间大小128M,slab chunk大小从20字节开始、增长因子为1.25、以nobody身份运行的memcache缓存空间,且显示详细过程
[root@node1 init.d]# /usr/local/memcached/bin/memcached -m 128 -n 20 -f 1.25 -vv -u nobody
slab class 1: chunk size 72 perslab 14563
slab class 2: chunk size 96 perslab 10922
slab class 3: chunk size 120 perslab 8738
slab class 4: chunk size 152 perslab 6898
slab class 5: chunk size 192 perslab 5461
slab class 6: chunk size 240 perslab 4369
slab class 7: chunk size 304 perslab 3449
slab class 8: chunk size 384 perslab 2730
slab class 9: chunk size 480 perslab 2184
slab class 10: chunk size 600 perslab 1747
slab class 11: chunk size 752 perslab 1394
slab class 12: chunk size 944 perslab 1110
slab class 13: chunk size 1184 perslab 885
slab class 14: chunk size 1480 perslab 708
slab class 15: chunk size 1856 perslab 564
slab class 16: chunk size 2320 perslab 451
slab class 17: chunk size 2904 perslab 361
slab class 18: chunk size 3632 perslab 288
slab class 19: chunk size 4544 perslab 230
slab class 20: chunk size 5680 perslab 184
slab class 21: chunk size 7104 perslab 147
slab class 22: chunk size 8880 perslab 118
slab class 23: chunk size 11104 perslab 94
slab class 24: chunk size 13880 perslab 75
slab class 25: chunk size 17352 perslab 60
slab class 26: chunk size 21696 perslab 48
slab class 27: chunk size 27120 perslab 38
slab class 28: chunk size 33904 perslab 30
slab class 29: chunk size 42384 perslab 24
slab class 30: chunk size 52984 perslab 19
slab class 31: chunk size 66232 perslab 15
slab class 32: chunk size 82792 perslab 12
slab class 33: chunk size 103496 perslab 10
slab class 34: chunk size 129376 perslab 8
slab class 35: chunk size 161720 perslab 6
slab class 36: chunk size 202152 perslab 5
slab class 37: chunk size 252696 perslab 4
slab class 38: chunk size 315872 perslab 3
slab class 39: chunk size 394840 perslab 2
slab class 40: chunk size 493552 perslab 2
slab class 41: chunk size 616944 perslab 1
slab class 42: chunk size 771184 perslab 1
slab class 43: chunk size 1048576 perslab 1
从显示的信息可以看到slab chunk的最小值系统默认为72个字节,按1.25倍增长到了1048576大小
[root@node1 init.d]# netstat -tunlp |grep memcached
tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN 9268/memcached
tcp 0 0 :::11211 :::* LISTEN 9268/memcached
udp 0 0 0.0.0.0:11211 0.0.0.0:* 9268/memcached
udp 0 0 :::11211 :::* 9268/memcached
可以看到监听在tcp和udp的11211端口
[root@node1 xinetd.d]# telnet localhost 11211
Trying ::1...
Connected to localhost.
Escape character is '^]'.
stats
STAT pid 9268
STAT uptime 1483
STAT time 1482739946
STAT version 1.4.33
STAT libevent 1.4.13-stable
STAT pointer_size 64
STAT rusage_user 0.209968
STAT rusage_system 1.007846
STAT curr_connections 10
STAT total_connections 12
STAT connection_structures 11
STAT reserved_fds 20
STAT cmd_get 0
STAT crawler_reclaimed 0
STAT crawler_items_checked 0
STAT lrutail_reflocked 0
END
add mykey 0 30 5 ##添加一个键,键名为mykey,flag为0,键的有效期为30秒,大小为5个字符
hello ##键值为hello
STORED ##显示已近%STORED
get mykey ##获取保存的键
VALUE mykey 0 5
hello ##键值为hello
END
get mykey
END
##30秒过去后,键值失效(虽然memcached为lazy模型,但过期后就不返回查询值)
quit
Connection closed by foreign host.
此外memcached还有以下常用命令: