首页 > 代码库 > Memcached详解
Memcached详解
1.Memcached介绍
Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。
Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信
2.Memcached的应用场景
2.1 作为数据库的前段缓存应用
1)完整缓存,静态缓存(易)
例如:商品分类,商品信息,将这些变动较少的(静态)数据提前存放到内存里,然后再对外提供服务。用户访问只读取memcached缓存,不读取数据库。
2)热点缓存(难)
需要前端程序配合,将热点数据存放到内存中,用户访问这些数据,直接访问到memcached缓存。第一次访问非热点数据时,memcached缓存没有,就访问数据库,获取数据返回给客户端,同时在memcached中缓存一份,第二次访问相同内容时,就不在访问数据库,用Memcached缓存直接返回数据。
2.2 作为集群的session会话共享存储
以php的web网站集群为例,可以通过修改php.ini
[root@server_02 html]# egrep "session.save" /etc/php.ini|grep -v ";" session.save_handler = files session.save_path = "/var/lib/php/session"
修改结果为:
session.save_handler = memcache --指定通过memcache进行缓存 session.save_path = "tcp://192.168.1.112:11211" --memcahced服务器的路径
2.3 memcached服务器的高可用方案
1) Memcached Repcached
一个单master单 slave的方案,但它的 master/slave都是可读写的,而且可以相互同步
2)memagent又名magent
每个magent节点又分别代理多个memcached服务节点,应用系统端使用magent pool来调用memcache进行存储。通过magent的连接池放的值会分别存在magent代理的所有memcached服务上去。
3)负载均衡器采用一直性哈希,将数据分散在若干个memcached服务器上
3.Memcached在业务中的工作流程
4.Memcached服务分布式集群实现方法
特殊说明:Memcached的调度算法一般用一致性hash,提高缓存命中率,每台Memcached都是一部分数据
1.程序端实现
程序加载所有的memcached服务器,通过对key进行hash(一致性哈希)存放缓存。
2.负载均衡器实现
通过对key进行hash(一致性哈希)存放缓存
注:一致性hash不但可以保证每个对象只请求对应唯一的memcahced服务器,而且保证单台缓存服务器宕机,更新的缓存数据最少
5.Memcached服务特点及工作原理
1.完全基于内存
2.节点之间相互独立
3.异步I/O模型,基于libevent模型的事件通知机制
4.缓存数据以key/value键值对形式存放
5.C/S模式架构,C语言编写,总共代码2000多行
6.数据存放在内存中,断电会丢失数据
7.缓存空间存放满之后,采用LRU算法删除过期缓存数据
6.Memcached内存管理机制
6.1 基本概念
1、slab class
在memcached中,对元素的管理是以slab为单元进行管理的。每个slab class对应一个或多个空间大小相同的chunk。参考下图一。
2、chunk
存放元素的最小单元。用户数据item(key、value等)最终会保存在chunk中。memcached会根据元素大小将其放到合适的slab class中。每一个slab class中的chunk空间大小是一样的,所以元素存放进来后,chunk可能会有部分空间剩余。参考下图二、下图三。
3、page
大小固定为1MB。当slab class空间不足时,就会申请page,并将page按chunk的大小进行切割。
图一 slab class逻辑结构图
图二 元素存入memcached会寻找最合适的slab class
图三 元素放入chunk时可能会有空间浪费
memcached使用自己的内存管理机制,可以有效避免系统内存碎片,避免给操作系统带来负担。
6.2 Memcached内存分配方式
启动memcached时,以-m指定大小的内存将会用于数据的存放。默认情况下,这些内存会被分隔成1M的page。每个page在必要时分配给slab class,然后根据slab class里chunk的大小,将page分隔成chunk。
一个page被赋给一个slab class后,它将不会再被移动。因为内存空间有限,如果在slab class 3中使用了较多的page,那么在slab class 4中就只能使用较少的page。可以这么认为,memcached是一个有很多更小的相互独立的缓存系统,每一个更小的缓存系统实际上就是slab class。每个slab class都有它自己的统计信息以及自己的LRU。
在启动memcached时,指定-vv参数,可以在启动日志中查看每个slab class的chunk大小。
[root@server_01 ~]# memcached -vv -u root slab class 1: chunk size 96 perslab 10922 slab class 2: chunk size 120 perslab 8738 slab class 3: chunk size 152 perslab 6898 slab class 4: chunk size 192 perslab 5461 slab class 5: chunk size 240 perslab 4369 slab class 6: chunk size 304 perslab 3449 slab class 7: chunk size 384 perslab 2730 slab class 8: chunk size 480 perslab 2184 slab class 9: chunk size 600 perslab 1747 slab class 10: chunk size 752 perslab 1394 slab class 11: chunk size 944 perslab 1110 slab class 12: chunk size 1184 perslab 885 slab class 13: chunk size 1480 perslab 708 slab class 14: chunk size 1856 perslab 564 slab class 15: chunk size 2320 perslab 451 slab class 16: chunk size 2904 perslab 361 slab class 17: chunk size 3632 perslab 288 slab class 18: chunk size 4544 perslab 230 slab class 19: chunk size 5680 perslab 184 slab class 20: chunk size 7104 perslab 147 slab class 21: chunk size 8880 perslab 118 slab class 22: chunk size 11104 perslab 94 slab class 23: chunk size 13880 perslab 75 slab class 24: chunk size 17352 perslab 60 slab class 25: chunk size 21696 perslab 48 slab class 26: chunk size 27120 perslab 38 slab class 27: chunk size 33904 perslab 30 slab class 28: chunk size 42384 perslab 24 slab class 29: chunk size 52984 perslab 19 slab class 30: chunk size 66232 perslab 15 slab class 31: chunk size 82792 perslab 12 slab class 32: chunk size 103496 perslab 10 slab class 33: chunk size 129376 perslab 8 slab class 34: chunk size 161720 perslab 6 slab class 35: chunk size 202152 perslab 5 slab class 36: chunk size 252696 perslab 4 slab class 37: chunk size 315872 perslab 3 slab class 38: chunk size 394840 perslab 2 slab class 39: chunk size 493552 perslab 2 slab class 40: chunk size 616944 perslab 1 slab class 41: chunk size 771184 perslab 1 slab class 42: chunk size 1048576 perslab 1
在slab class 1中,每个chunk大小为96字节,每个页面包含10922个chunk(或item)。这两个数相乘,应该最近接1个page的大小(默认是1MB)。
当存储元素时,它们将被放到最合适的slab class中。例如,50字节的元素(包含key、value等信息)将被存放到slab class 1中的chunk,根据之前的说明,此chunk中将会有30字节的空间浪费。如果存放数据总共有90字节,将被存放到slab class 2中,此时会有14字节的空间浪费。
6.3 Memcached优化
Memcached启动时,通过设置参数-f,可以设置每个slab class下chunk的空间增长率。尽量使每个chunk的size接近具体业务的size,减少内存空间浪费,提高内存利用率
6.4 Memcached内存回收
与redis不同的是,memcached不会主动回收内存。memcached会重复使用失效数据的内存。
如果获取了一个已失效的数据,memcached将会释放内存。后续再将新的数据存放进来时,将会重用此内存。
根据LRU(最近最少使用)算法,元素将被踢出以让给新的元素,或发现有过期的元素,它们的内存将被重用。如果元素还没有失效(失效日期为0或者将会在将来失效),slab class已经用完了所有空闲的chunk,并且没有空闲的page可以分配给此slab class,此时将会执行LRU算法,踢出数据。
6.5 LRU算法
当存放新的元素时,内存也可能会被回收。如果在相应的slab class里,既没有空闲的chunk,也没有空闲的page,memcached将会使用LRU算法查找应该被回收的元素。它将会查找LRU列表中尾部(最近最少使用)的一些元素,看它们是否已经失效,如果存在失效的元素,则将此元素占用的空间重用。如果找不到失效的元素,那么将踢出最尾部还没有失效的元素。
7.Memcached安装配置
1)安装libevent(前提)
yum install libevent libevent-devle -y
也可以通过编译安装libevent包
2)安装Memcached服务端
说明:Memcached是服务端
Memcache是客户端
[root@server tools]# wget http://memcached.org/files/memcached-1.4.31.tar.gz [root@server_02 tools]# tar xf memcached-1.4.31.tar.gz [root@server_02 tools]# cd memcached-1.4.31 [root@server_02 memcached-1.4.31]# ./configure [root@server_02 memcached-1.4.31]# make && make install
3)启动memcached服务
[root@server_02 memcached-1.4.31]# memcached -d -m 10m -u root -l 192.168.1.112 -p 11211-c 256 -P /tmp/memcached.pid [root@server_02 memcached-1.4.31]# ss -lntup|grep memcached udp UNCONN 0 0 192.168.1.112:11211 *:* users:(("memcached",833,27),("memcached",833,28),("memcached",833,29),("memcached",833,30)) tcp LISTEN 0 128 192.168.1.112:11211 *:* users:(("memcached",833,26)) [root@server_02 memcached-1.4.31]#
-d选项是以一个守护进程启动,
-m是分配给Memcache使用的内存数量,单位是MB,我这里是10MB,
-u是运行Memcache的用户,我这里是root,
-l是监听的服务器IP地址,如果有多个地址的话,我这里指定了服务器的IP地址192.168.1.112
-p是设置Memcache监听的端口,最好是1024以上的端口,默认是11211
-c选项是最大运行的并发连接数,默认是1024,我这里设置了256,按照你服务器的负载量来设定,
-P是设置保存Memcache的pid文件,我这里是保存在 /tmp/memcached.pid,
注意:可以通过更改端口号,实现启动多个memcached实例
4)关闭memcached服务
1.pkill memcached
2.kill `cat /tmp/memcached.pid`
5) memcached存储数据测试(nc/telnet测试)
[root@server_02 memcached-1.4.31]# telnet 192.168.1.112 11211 Trying 192.168.1.112... Connected to 192.168.1.112. Escape character is ‘^]‘. set key key2 0 0 4 CLIENT_ERROR bad command line format set key1 0 60 4 youd STORED get key1 VALUE key1 0 4 youd END delete key1 DELETED get key1 END
命令说明:
<command name> <key> <flags> <exptime> <bytes>\r\n <data block>\r\n
a) <command name> 可以是”set”, “add”, “replace”。
“set”表示按照相应的<key>存储该数据,没有的时候增加,有的覆盖。
“add”表示按照相应的<key>添加该数据,但是如果该<key>已经存在则会操作失败。
“replace”表示按照相应的<key>替换数据,但是如果该<key>不存在则操作失败
b) <key> 客户端需要保存数据的key。
c) <flags> 是一个16位的无符号的整数(以十进制的方式表示)。
该标志将和需要存储的数据一起存储,并在客户端get数据时返回。
客户可以将此标志用做特殊用途,此标志对服务器来说是不透明的。
d) <exptime> 过期的时间。
若为0表示存储的数据永远不过时(但可被服务器算法:LRU 等替换)。
如果非0(unix时间或者距离此时的秒数),当过期后,服务器可以保证用户得不到该数据(以服务器时间为标准)。
e) <bytes> 需要存储的字节数(不包含最后的”\r\n”),当用户希望存储空数据时,<bytes>可以为0
f) 最后客户端需要加上”\r\n”作为”命令头”的结束标志。
<data block>\r\n
紧接着”命令头”结束之后就要发送数据块(即希望存储的数据内容),最后加上”\r\n”作为此次通讯的结束。
linux nc命令操作memcache方法实例
1)存储数据:printf “set key 0 10 6\r\nresult\r\n” |nc 192.168.1.112 11211
2)获取数据:printf “get key\r\n” |nc 192.168.1.112 11211
3)删除数据:printf “delete key\r\n” |nc 192.168.1.112 11211
4)查看状态:printf “stats\r\n” |nc 192.168.1.112 11211
5)模拟top命令查看状态:watch “echo stats” |nc 192.168.1.112 11211
6)清空缓存:printf “flush_all\r\n” |nc 192.168.1.112 11211 (小心操作,清空了缓存就没了
6)php安装memcache客户端(扩展memcache模块)
参考:http://php.net/manual/zh/memcache.installation.php
tar xf memcache-3.0.6.tgz cd memcache-3.0.6 phpize ./configure --enable-memcache --with-php-config=/usr/bin/php-config --with-zlib-dir make && make install
安装成功后,修改php.ini文件的一下两项内容:
[root@server_02 html]# egrep "memcache.so|extension" /etc/php.ini|grep -v ";"
extension_dir = "/usr/lib64/php/modules/" ---扩展模块的目录
extension = memcache.so - --扩展的模块名称
用phpinfo查看下memcache是否加载成功
7)php程序测试memcached
php测试页面代码:
[root@server_02 html]# vim memcache.php <?php $memcache = new Memcache; $memcache->connect(‘192.168.1.112‘, 11211); $memcache->set(‘test‘, ‘successs‘); echo $memcache->get(‘test‘); ?>
将以上代码,放到memcache.php文件中,将memcache.php文件放到web服务目录下/var/www/html里
php页面显示内容:
8.memcached服务的web管理工具memadmin
wget http://www.junopen.com/memadmin/memadmin-1.0.12.tar.gz tar xf memadmin-1.0.12.tar.gz mv ./memadmin /var/www/html/memadmin --将memadmin目录移动到web服务器目录下
memadmin默认账号密码都是:admin
memadmin网页效果图:
常见问题:
1.如果启动Memcached服务的时候遇到了
/usr/local/bin/memcached: error while loading shared libraries: libevent-1.2.so.1: cannot open shared object file: No such file or directory;
解决方案:
[root@localhost bin]# LD_DEBUG=libs memcached -v
[root@localhost bin]# ln -s /usr/lib/libevent-1.2.so.1 /usr/lib64/libevent-1.2.so.1
[root@localhost bin]# /usr/local/bin/memcached -d -m 100 -u root -p 11211 -c 1000 -P /tmp/memcached.pid
[root@localhost bin]# ps -aux
可以看到启动的Memcached服务了.
2.把Memcached服务加载到Linux的启动项中.万一机器断电系统重启.那么Memcached就会自动启动了.
假如启动Memcache的服务器端的命令为:
# /usr/local/bin/memcached -d -m 10 -u root -l 192.168.1.112 -p 11211 -c 256 -P /tmp/memcached.pid容来自17jquery
想开机自动启动的话,只需在/etc/rc.d/rc.local中加入一行,下面命令
/usr/local/memcached/bin/memcached -d -m 10 -p 12000 -u apache -c 256
上面有些东西可以参考一下:即,ip不指定时,默认是本机,用户:最好选择是:apache 或 deamon
本文出自 “秦仙儿” 博客,请务必保留此出处http://youdong.blog.51cto.com/3562886/1860165
Memcached详解