Memcached详解

一、memcached 是什么

二、memcached 特点

三、memcached内存分配机制

四、分布式缓存中三种负载均衡的方法

五、memcached 过期方式

六、memcached 基于libevent的事件处理

七、memcached的安装

八、memcached 的使用和配置

九、memcached 命令使用详解

十、安装PHP的扩展Memcached实现lnmp+memcached

十一、Nginx整合memcached


缓存服务器的类型:

透传式缓存:首先得有代理功能,工作在真实服务器前端,请求先到达缓存服务器,缓存服务器中有该请求的数据并在有效期内就直接使用缓存响应给用户,如果没有或过期则缓存服务器请求向后端的服务器请求该数据响应给客户并根据协议决定是否缓存在本地,缓存服务器对于客户端是透明的

旁挂式缓存:工作在真实服务器后端,在真实服务器上要查询数据时,应用程序调用memcached的客户端|驱动首先查询memcached,如果memcached中有相应的缓存数据,取得数据并响应给用户,如果memcahed中没有相应的缓存数据则真实服务器向mysql中查询,并根据协议决定是否把查询结果缓存在memcached上。


实现多个缓存服务器做互为备分,真实服务器双写,有开源软件实现这个功能。

两个开源站点:sourceforge.net,github.com

一、memcached 是什么

       Memcached是一款开源、高性能、分布式内存对象缓存系统,可应用各种需要缓存的场景,

其主要目的是通过降低对Database的访问来加速web应用程序

它是一个基于内存的“键值对”存储,用于存储数据库调用、API调用或页面引用结果的直接数据,如字符串、对象等。

Memcached是以LiveJournal旗下Danga Interactive 公司的Brad Fitzpatric 为首开发的一款软件。现在已成为mixi、hatena、Facebook、Vox、LiveJournal等众多服务中提高Web应用扩展性的重要因素。

       许多Web应用都将数据保存到RDBMS(关系型数据库管理系统)中,应用服务器从中读取数据并在浏览器中显示。 但随着数据量的增大、访问的集中,就会出现RDBMS的负担加重、数据库响应恶化、 网站显示延迟等重大影响。

       这时就该memcached大显身手了,通过缓存数据库查询结果,减少对数据库访问次数,来加速Web应用程序的速度、 提高可扩展性。如下图,

m1

二、memcached 特点

Memcached是一款开发工具,它既不是一个代码加速器,也不是数据库中间件。

其设计哲学思想主要反映在如下方面:

  • 简单key/value存储:服务器不关心数据本身的意义及结构,只要是可序列化数据即可。

    存储项由“键、过期时间、可选的标志及数据”四个部分组成;

  • 功能的实现一半依赖于客户端,一半基于服务器端:客户负责发送存储项至服务器端、从服务端获取数据以及无法连接至服务器时采用相应的动作;服务端负责接收、存储数据,并负责数据项的超时过期;

  • 各服务器间彼此无视:不在服务器间进行数据同步;

  • O(1)的执行效率

  • 清理超期数据:默认情况下,Memcached是一个LRU缓存,同时,它按事先预订的时长清理超期数据;但事实上,memcached不会删除任何已缓存数据,只是在其过期之后不再为客户所见;而且,memcached也不会真正按期限清理缓存,而仅是当get命令到达时检查其时长;

    Memcached的服务器客户端通信并不使用复杂的XML等格式, 而使用简单的基于文本格式和二进制格式。因此,通过telnet 也能在memcached上保存数据、取得数据。

三、Memcached内存分配机制

1、Slab Allocation机制

     memcached默认情况下采用了名为Slab Allocator的机制分配、管理内存。在该机制出现以前,内存的分配是通过对所有记录简单地进行malloc()和free()来进行的。但是,这种方式会导致内存碎片,加重操作系统内存管理器的负担,最坏的情况下,会导致操作系统比memcached进程本身还慢。

Slab Allocator就是为解决该问题而诞生的。

Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,以完全解决内存碎片问题。

2、Slab Allocation的主要术语

   1)page:分配给Slab用于切割的内存空间,默认是1MB。分配给Slab之后根据slab的大小切分成chunk

   2)chunk:存放数据的最小单元。用户数据item(key、value等)最终会保存在chunk中。

   3)slab class特定大小的chunk的组,在memcached中,对数据的管理是以slab为单元进行管理的。

每个slab class对应一个或多个空间大小相同的chunk。参考下图一。

             图一  slab class逻辑结构图

3、在Slab中缓存记录的原理

下面说明memcached如何针对客户端发送的数据选择slab并缓存到chunk中

memcached根据收到的数据的大小,选择最适合数据大小的slab(图2)。memcached中保存着slab内空闲chunk的列表,根据该列表选择chunk,然后将数据缓存于其中。

2033581_137843557732cq.png

                     图2 选择存储记录的组的方法

4、Slab Allocator的缺点

Slab Allocator解决了当初的内存碎片问题,但新的机制也给memcached带来了新的问题。

这个问题就是,由于分配的是特定长度的内存,因此无法有效利用分配的内存。

例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了(图3)。

m3

                       图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.

就是说,如果预先知道客户端发送的数据的公用大小,或者仅缓存大小相同的数据的情况下,只要使用适合数据大小的组的列表,就可以减少浪费。

但是很遗憾,现在还不能进行任何调优,只能期待以后的版本了。

但是,我们可以通过设置growth factor(增长系数/因子)选项来调节slab class的大小的差别

四、分布式缓存中三种负载均衡的方法

第一种:传统的数据分布方法,将key的hash值对机器数取模

    对用户的检索关键词分词后进行hash然后对hash出的数对4(缓存服务器的个数)取模,余数为1则分配到,服务器1上,为2分配到2上,依次类推。

    这个算法的实现非常简单,计算hash(key)/n,n为机器数,得到的值就是该key需要路由到的服务器编号了。

    优点:实现简单

    缺点:在服务器数量发生变化的时候,缓存会大量失效。 

第二种:一致性hash 

    试想下如果使用传统取模算法。如果有一个key要存到缓存中,根据hash(key)/n (n表示有n台缓存服务器),可以计算出缓存所在的服务器id。这个时候有一台服务器挂掉了,剩下n-1台服务器。这时候,同样一个key,根据hash(key)/(n-1) ,这个时候就命中不了缓存了,基本所有的缓存都会失效,这个情况在线上可能是灾难性的。 一致性hash可以解决部分问题。

    通常可以考虑[0,(2^32-1)]为hash值的取值范围。我们可以把取值范围想象成一个闭环,2^32-1 和 0 相连接。如下图所示。

    技术分享

技术分享

   这个时候假设我们有4个缓存服务器节点。(node1~node4) 首先计算这四个值的hash值,并且这四个点占据了闭环的四个位置,如上图所示,这个时候需要根据key来路由缓存服务器,首先计算hash(key)值(这个hash算法需要保证hash(key)的值落在在区间[0,2^32-1]中)。然后我们可以想象这个hash(key)值位于闭环的其中一个点,然后用这个hash(key)依次加一,直到命中其中一个node为止,命中的node就是key需要路由的服务器,如上图,需要找到key2的缓存值所在的服务器,首先计算hash(key2),落在如图的闭环中,然后顺时针找到离这个hash值最近的node,可以看到是node1。key2对应的缓存值就存在node1中。

    如果这个时候如果增加了节点node5如下图:

技术分享

    技术分享

        看下缓存失效的情况,如上图,只有hash(key)落在node4~node5之间的key才会有影响,在未增加node5之前落在这个范围的key最终路由到node1,增加node5之后路由到node5了,缓存失效了。除此之外,落在其他范围的hash值就不受影响。如上图,增加node5之后key6原来会路由到node1的,现在路由到node5。而key1不受影响,还是路由到node1。

    同理,如果少掉一个节点,还是上图为例,假如这个时候node5失效了,node5失效之前落在node4~node5之间的hash值,会路由到node5,失效之后会路由到node1,也就是原本落在node4~node5之间的hash值失效了。由此可见一致性hash能在节点变动的时候减少缓存失效的比例。  

    还有一种情况,当cache的数量很少的或者缓存服务器很少的时候,会导致缓存分布不均衡。如下图所示:
 技术分享

    当只有很少节点的时候,例如上图的两个,这个时候就会分配得很不均衡。

这个时候引入一个叫虚拟节点的概念,原理就是增加更多的虚拟节点,让每个节点承受的压力尽量均衡。

这些增加的节点并不是真正新增的服务器节点,而是由原来的节点”复制“出来的。

例如下图,”复制“了两个新节点,node3,node4。实际上,落到node3,node4的key最终访问的服务器是node2,node1.
技术分享

    这样就可以把压力尽量分配到各个机器上。另外需要维护一张表格,用来记录虚拟节点指向的真正节点。 

    优点:相比简单的对机器数取模算法,当节点变动的时候只有相对较少的key失效,实现也相对简单。不需要进行数据迁移,每个服务器是独立的。

    缺点:还是会有部分的key失效,如果访问量非常大的时候,如果访问到失效的key的时候,就会直接访问到数据源上面去了,可能会导致数据源直接压挂。
  

第三种:tair负载均衡算法,构造一张对照表
 

    首先看下如何构建一张对照表。

    tair中数据的存储是以bucket为单位的,一个bucket对应一个dateServer,一个dateServer中会有多个bucket。bucket的数目是固定的,这里假设bucket的数量为1024个,并且每个bucket有属于自己的id,依次从0到1023。如下图:
技术分享
    可以看到对key进行hash之后首先会路由到某个bucket然后根据对应关系,再路由到对应的dataServer。    
在tair中,你可以设置同一个bucket的备份数目,我们称其中一个bucket为master,其他的备份称为slave。configServer启动的时候会构造三张bucket和dataServer的对照表,分别是hash_table, m_hash_table, d_hash_table,这三张对照表在初始构建的时候都是一样的,但是在dataServer发生增加的时候会暂时不一样,但是最终会趋向一致,三张表分别有什么用处下面会讲到。configServer在构建对照表的时候有两种模式,一种是均衡模式,这种模式会尽量保证每个节点的bucket数目差不多。一种是安全模式,这种模式会尽量保证一份数据以及它的备份分配在不同的区域的服务器上。client通过configServer获取对照表(hash_table)之后,根据(hash(key)%bucket的总数)算出bucket的id并且参照对照表,就能知道这个key对应的dataServer了。对照表的结构大概如下(这里为了简化,一共只有5个bucket,4个dataServer(ds1,ds2,ds3,ds4),这个是初始时的对照表,hash_table, m_hash_table, d_hash_table的内容都是一样的)。

    技术分享
 

    当服务器变化之后configserver是如何重构对照表的?重构对照表的时候,数据是怎么迁移的?

    configServer会定时发送心跳包给dataServer,用来检测dataServer是否还存活,如果没有存活的话就会重新构造对照表。或者如果有新加dataServer的话也会重新构造对照表。

当有一个dataServer当机之后,这个机器 上的存储的bucket数据都会丢失,如果是master bucket丢失之后其中一个slave bucket会补上成为master bucket。至于选择哪个slave bucket成为master bucket的是根据slave 上负载的master bucket有没有超标,并且总bucket数有没有超标等标准。举个例子,上图中当ds2失效之后,hash_table, m_hash_table, d_hash_table三个表分别是这样子的。

 hash_table :
 技术分享

m_hash_table:

 技术分享 

d_hash_table:
 技术分享

    hash_table发送给client,client不至于不能工作,m_hash_table和d_hash_table发送到dataServer,dataServer根据这两张表就可以知道自己是否需要迁移数据和迁移到哪里了。例如这里第一列,第三排,对比两表,可以知道,ds1需要把数据迁移到ds4。 

   如果是要增加新的dataServer,原理就差不多了,configServer新建对照表,然后把对照表发送到dateServer,然后dataServer再根据新对照表来做数据迁移,完成之后,client就可以使用新的对照表了。

    优点:当需要增加机器的时候,不会有key失效。

    缺点:实现比较复杂,需要进行数据的迁移。

五、memcached 过期方式

数据过期方式:Lazy Expiration + LRU

1.Lazy Expiration(惰性过期)

根据缓存对象的ttl进行清理

       memcached内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期。这种技术被称为lazy(惰性)expiration。因此,memcached不会在过期监视上耗费CPU时间。

2.LRU(最近最少使用算法)

       memcached会优先使用已超时的记录的空间,但即使如此,也会发生追加新记录时空间不足的情况,此时就要使用名为 Least Recently Used(LRU)机制来分配空间。当memcached的内存空间不足时(无法从slab class 获取到新的空间时),就从最近未被使用的记录中搜索,并将其空间分配给新的记录。可以支持禁用此功能

六、memcached 基于libevent的事件处理

       libevent是个程序库,它将Linux的epoll、epool,select,BSD类操作系统的kqueue等事件处理功能封装成统一的接口。即使对服务器的连接数增加,也能发挥O(1)的性能。memcached使用这个libevent库,因此能在Linux、BSD、Solaris等操作系统上发挥其高性能。 

memcached依赖于libevent API,因此要事先安装之,项目主页:http://libevent.org/,

读者可自行选择需要的版本下载。可以使用yum安装libevent

也可以使用源码包编译安装。安装过程:

# tar xf libevent-2.0.21-stable.tar.gz
# cd libevent-2.0.21
# ./configure --prefix=/usr/local/libevent
# make && make install
# echo "/usr/local/libevent/lib" > /etc/ld.so.conf.d/libevent.conf
# ldconfig

七、memcached 安装

1、直接yum安装

[root@BAIYU_173 yum.repos.d]# yum install memcached -y
[root@BAIYU_173 ~]# rpm -ql memcached
/etc/rc.d/init.d/memcached
/etc/sysconfig/memcached
/usr/bin/memcached
/usr/bin/memcached-tool
/usr/share/doc/memcached-1.4.4
/usr/share/doc/memcached-1.4.4/AUTHORS
/usr/share/doc/memcached-1.4.4/CONTRIBUTORS
/usr/share/doc/memcached-1.4.4/COPYING
/usr/share/doc/memcached-1.4.4/ChangeLog
/usr/share/doc/memcached-1.4.4/NEWS
/usr/share/doc/memcached-1.4.4/README
/usr/share/doc/memcached-1.4.4/protocol.txt
/usr/share/doc/memcached-1.4.4/readme.txt
/usr/share/doc/memcached-1.4.4/threads.txt
/usr/share/man/man1/memcached.1.gz
/var/run/memcached

2、编译安装

 1)安装libevent

注,在上文中提到memcached是基于libevent进行事件处理的,所以我们得先安装libevent。

[root@memcache src]# tar xf libevent-2.0.21-stable.tar.gz
[root@memcache src]# cd libevent-2.0.21-stable
[root@memcache libevent-2.0.21-stable]# ./configure --prefix=/usr/local/libevent
[root@memcache libevent-2.0.21-stable]# make && make install

 2)安装memcached

[root@memcache src]# tar xf memcached-1.4.15.tar.gz
[root@memcache src]# cd memcached-1.4.15
[root@memcache memcached-1.4.15]# ./configure --prefix=/usr/local/memcached --with-libevent=/usr/local/libevent
[root@memcache memcached-1.4.15]# make && make install

 3)后续配置

[root@memcache ~]# vim /etc/profile.d/memcache.sh 
[root@memcache ~]# cat /etc/profile.d/memcache.sh  
export PATH=$PATH:/usr/local/memcached/bin/  
[root@memcache ~]# source /etc/profile

八、memcached使用和配置

1、memcached选项

  • -p TCP监听端口 (default: 11211),小写

  • -U UDP 监听端口 (default: 11211, 0 is off),大写

  • -s UNIX socket监听路径,不支持网络

  • -a UNIX socket访问掩码, 八进制 (default: 0700)

  • -l 监听的服务器IP地址 (default: all addresses)

  • -d 运行为守护进程

  • -r 最大限度利用核心文件限制

  • -u 运行memcached用户

  • -m #:最大的内存使用 (default: 64 MB),也不宜过大

  • -M 内存耗尽返回错误,而不是删除缓存对象,

  • -c 最大并发连接 (default: 1024)

  • -k 锁定所有分页内存

  • -v 输出警告和错误信息

  • -vv 同时打印客户端请求和返回信息

  • -vvv 打印内部状态转换信息

  • -i 打印memcached 和 libevent 版本信息

  • -P 设置保存pid文件, only used with -d option

  • -f 指定增长因子|倍数 (default: 1.25)

  • -n key+value+flags最小分配空间(default: 48)

  • -L 尝试使用大内存页。增加内存页大小可以减少失误的TLB数量,提高性能。

  • -D 指定key和IDs的分隔符 default is “:” (colon). 如果指定此选项,统计信息收集自动开启;

  • -t 使用的线程数量 (default: 4)

  • -R 每个事件的最大请求数 (default: 20)

  • -C 禁止使用 CAS

  • -b 设置积压队列数限制 (default: 1024)、

  • -B 绑定协议 �C one of ascii, binary, or auto (default)

  • -I 分配给每个slab页(default: 1mb, min: 1k, max: 128m)

  • -o 配置额外选项

2、启动memcached

[root@BAIYU_173 ~]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
saslauth:x:499:76:Saslauthd user:/var/empty/saslauth:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
memcached:x:498:499:Memcached daemon:/var/run/memcached:/sbin/nologin
[root@BAIYU_173 ~]# memcached -u memcached -vv
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
<26 server listening (auto-negotiate)
<27 send buffer was 8388608, now 268435456
<27 server listening (udp)
<27 server listening (udp)
<27 server listening (udp)
<27 server listening (udp)

从输出结果可以看到memcached的内存分配过程:

[root@BAIYU_173 ~]# service memcached start
正在启动 memcached:[确定]
[root@BAIYU_173 ~]# netstat -nlptu
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name   
tcp        0      0 0.0.0.0:11211               0.0.0.0:*                   LISTEN      25006/memcached     
tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      1455/sshd           
tcp        0      0 127.0.0.1:25                0.0.0.0:*                   LISTEN      1552/master         
udp        0      0 0.0.0.0:11211               0.0.0.0:*                               25006/memcached

3、memcached 基本命令

Memcached提供了为数不多的几个命令来完成与服务器端的交互,这些命令基于memcached的协议实现。

存储类命令:set, add, replace, append(在一个缓存后附加内容), prepend(在一个缓存之前附加内容)

获取数据类命令:get, delete, incr/decr(自加1/自减1)

统计类命令:stats, stats items, stats slabs, stats sizes

清理命令: flush_all


add命令

add keyname flag(修饰符)  timeout  datasize

如:

add mykey 0(表示没有修饰符) 10(生成周期) 12(数据大小)

Hello world!


get命令:

get keyname

如:get mykey

VALUE mykey 0 12

Hello world!

END

[root@BAIYU_173 ~]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
add 4key 0 20 3
abc
STORED
get mykey
END
get 4key
VALUE 4key 0 3
abc
END
add 4key 0 20 3
abc

九、memcached 常用命令

(1).增加值命令

说明:无论如何都添加或更新的set 命令 (值不存在则添加,存在则更新)  set设置后可以用get命令获取值,也可以使用delete命令删除该值。

[root@memcache ~]# telnet 192.168.18.201 11211
Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
set mykey 0 0 3
100
STORED
get mykey
VALUE mykey 0 3
100
END
delete mykey
DELETED
get mykey
END

说明:只有数据不存在时添加值的add命令。

[root@memcache ~]# telnet 192.168.18.201 11211
Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
add mykey 0 0 4 #第一次添加成功
test
STORED
add mykey 0 0 4 #第二次添加失败
test
NOT_STORED

说明:只有数据存在时替换的replace命令。

[root@memcache ~]# telnet 192.168.18.201 11211
Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
replace testkey 0 0 2 #元素不存在替换失败
11
NOT_STORED
add testkey 0 0 2
22
STORED
get testkey
VALUE testkey 0 2
22
END
replace testkey 0 0 3 #元素存在替换成功
100
STORED
get testkey
VALUE testkey 0 3
100
END

(2).删除命令 delete

get mykey
VALUE mykey 0 3
100
END
delete mykey
DELETED
get mykey
END

(3).读取命令

说明:get 命令 获取一个键或多个键的值 多个键以空格分开。

[root@memcache ~]# telnet 192.168.18.201 11211
Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
set mykey 0 0 2
10
STORED
set testkey 0 0 2
20
STORED
get mykey testkey
VALUE mykey 0 2
10
VALUE testkey 0 2
20
END

说明:gets 命令比get返回的值多一个数字,用来判断数据是否发生过改变。

[root@memcache ~]# telnet 192.168.18.201 11211
Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
set mykey 0 0 2
10
STORED
set testkey 0 0 2
20
STORED
get mykey testkey
VALUE mykey 0 2
10
VALUE testkey 0 2
20
END
gets mykey testkey
VALUE mykey 0 2 5
10
VALUE testkey 0 2 6
20
END
set testkey 0 0 2
30
STORED
gets mykey testkey
VALUE mykey 0 2 5
10
VALUE testkey 0 2 7
30
END

说明:cas 的意思是 check and set 的意思,只有当最后一个参数gets获取的那个用来判断数据发生改变的那个值相同时才会存储成功,否则返回 exists。

[root@memcache ~]# telnet 192.168.18.201 11211
Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
gets mykey
VALUE mykey 0 2 5
10
END
cas mykey 0 0 2 6
50
EXISTS
cas mykey 0 0 2 5              
50
STORED
gets mykey
VALUE mykey 0 2 8
50
END

说明:自曾(incr) 自减(decr)命令。

[root@memcache ~]# telnet 192.168.18.201 11211

Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
set age 0 0 2
10
STORED
get age
VALUE age 0 2
10
END
incr age 2
12
incr age 2
14
get age
VALUE age 0 2
14
END
decr age 1
13
get age
VALUE age 0 2
13
END

(4).状态命令

说明:stats 显示memcachd状态。

[root@memcache ~]# telnet 192.168.18.201 11211
Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
stats
STAT pid 8279 #进程ID
STAT uptime 8000 #服务器运行秒数
STAT time 1378284623 #服务器当前unix时间戳,秒
STAT version 1.4.15 #服务器版本
STAT libevent 2.0.21-stable #libevent版本号
STAT pointer_size 64 #操作系统指针大小(这台服务器是64位的)
STAT rusage_user 0.000999  计用户时间
STAT rusage_system 0.003999 #进程累计系统时间
STAT curr_connections 10 #当前打开连接数
STAT total_connections 11 #曾打开的连接总数
STAT connection_structures 11 #服务器分配的连接结构数
STAT reserved_fds 20 #内部使用的FD数
STAT cmd_get 0 #执行get命令总数
STAT cmd_set 0 #执行set命令总数
STAT cmd_flush 0 #执行flush命令总数
STAT cmd_touch 0 #执行touch命令总数
STAT get_hits 0 #get命中次数
STAT get_misses 0 #get未命中次数
STAT delete_misses 0 #delete未命中次数
STAT delete_hits 0 #delete命中次数
STAT incr_misses 0 #incr未命中次数
STAT incr_hits 0 #incr命中次数
STAT decr_misses 0 #decr未命中次数
STAT decr_hits 0 #decr命中次数
STAT cas_misses 0 #cas未命中次数
STAT cas_hits 0 #cas命中次数
STAT cas_badval 0 #使用擦拭次数
STAT touch_hits 0 #touch命中次数
STAT touch_misses 0 #touch未命中次数
STAT auth_cmds 0 #认证处理的次数
STAT auth_errors 0 #认证失败次数
STAT bytes_read 7 #读取字节总数
STAT bytes_written 0 #写入字节总数
STAT limit_maxbytes 134217728 #现在的内存大小为128M
STAT accepting_conns 1 #目前接受的新接数
STAT listen_disabled_num 0 #失效的监听数
STAT threads 4 #当前线程数
STAT conn_yields 0 #连接操作主支放弃数目
STAT hash_power_level 16 #hash等级
STAT hash_bytes 524288 #当前hash表等级
STAT hash_is_expanding 0 #hash表扩展大小
STAT bytes 0 #当前存储占用的字节数
STAT curr_items 0 #当前存储数据总数
STAT total_items 0 #启动以来存储的数据总数
STAT expired_unfetched 0 #已过期但未获取的对象数目
STAT evicted_unfetched 0 #已驱逐但未获取的对象数目
STAT evictions 0 #LRU释放的对象数目
STAT reclaimed 0 #用已过期的数据条目来存储新数据的数目
END

说明 :flush_all 清空所有项目。

[root@memcache ~]# telnet 192.168.18.201 11211
Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
set mykey 0 0 2
10
STORED
set age 0 0 2
20
STORED
get mykey age
VALUE mykey 0 2
10
VALUE age 0 2
20
END
flush_all
OK
get mykey age
END

说明:后续追加append和prepend前面插入命令。

[root@memcache ~]# telnet 192.168.18.201 11211
Trying 192.168.18.201...
Connected to 192.168.18.201.
Escape character is '^]'.
set age 0 0 2
13
STORED
get age
VALUE age 0 2
13
END
append age 0 0 6
111111
STORED
get age
VALUE age 0 8
13111111
END
prepend age 0 0 6
111111
STORED
get age
VALUE age 0 14
11111113111111
END

flush_all 实际上没有立即释放项目所占用的内存,而是在随后陆续有新的项目被储存时执行(这是由memcached的懒惰检测和删除机制决定的)。flush_all 效果是它导致所有更新时间早于 flush_all 所设定时间的项目,在被执行取回命令时命令被忽略。

十、安装Memcached的PHP扩展

程序员在开发,自行调用了memcached的API,memcached的功能才能生效

Memcached:服务器

memcached:php连接memacached服务可以使用的扩展

memcache:php连接memcache服务可以使用的另一个扩展(性能更好)

libmemcached:c库

这里我用上篇博文安装好的Lnmp环境来安装memcache

环境:

192.168.100.10 CentOS6.5-x86_64 lnmp+memcache

192.168.100.173 CentOS6.5-x86_64 memcached

1、安装php的memcache扩展

[root@www ~]# ls memcache-2.2.7.tgz 
memcache-2.2.7.tgz
[root@www ~]# tar xf memcache-2.2.7.tgz 
[root@www ~]# cd memcache-2.2.7
[root@www memcache-2.2.7]# ls
config9.m4  example.php                 memcache.php        memcache_standard_hash.c
config.m4   memcache.c                  memcache_queue.c    php_memcache.h
config.w32  memcache_consistent_hash.c  memcache_queue.h    README
CREDITS     memcache.dsp                memcache_session.c

注意:此时并没有configure文件,memcache是作为php的插件运行

[root@www memcache-2.2.7]# /usr/local/php/bin/phpize   #如果是yum安装的php,要安装了php-devel包才有这个命令
Configuring for:
PHP Api Version:         20131106
Zend Module Api No:      20131226
Zend Extension Api No:   220131226
[root@www memcache-2.2.7]# ./configure --with-php-config=/usr/local/php/bin/php-config --enable-memcache
[root@www memcache-2.2.7]# make && make install

上述安装完后会有类似以下的提示:

Installing shared extensions:     /usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/memcached.so

编辑/etc/php.ini,在“动态模块”相关的位置添加如下一行来载入memcache扩展:

extension = /usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/

查看phpinfo页面可以看到已经有了memcache扩展wKioL1ZMTKfgn2anAACPxdw61rQ977.jpg

而后对memcached功能进行测试,在网站目录中建立测试页面test.php,添加如下内容:

[root@www ~]# vi /www/a.com/test.php 
<?php
    $mem = new Memcache;
    $mem->connect("192.168.100.173", 11211)  or die("Could not connect");

    $version = $mem->getVersion();
    echo "Server's version: ".$version."<br/>\n";

    $mem->set('hellokey', 'Hello World', 0, 600) or die("Failed to save data at the memcac
hed server");
    echo "Store data in the cache (data will expire in 600 seconds)<br/>\n";

    $get_result = $mem->get('hellokey');
    echo "$get_result is from memcached server.";
?>

测试:

wKiom1ZMbdDgHU9dAABp643w380102.png

2、memcached图形工具

 1)memcachephp

[root@www ~]# ls memcachephp.zip 
memcachephp.zip
[root@www ~]# unzip memcachephp.zip                
Archive:  memcachephp.zip
  inflating: memcache.php            
[root@www ~]# mv memcache.php /www/a.com/
[root@www ~]# ls /www/a.com/
admin  index.html  index.php  memcache.php  test.php

vi memcache.php可以看到里面定义了管理员默认登录用户和密码,并设置要连接memcached服务器

$MEMCACHE_SERVERS[] = '192.168.100.173:11211';

测试:

wKioL1ZMfXnA3Pb6AAE6yfXUyuI819.png

可以查看缓存服务器详细使用状态,

 2)memadmin-master(中文界面)

MemAdmin是一款可视化的Memcached管理与监控工具,使用PHP开发,体积小,操作简单。

主要功能:

  • 服务器参数监控:STATS、SETTINGS、ITEMS、SLABS、SIZES实时刷新

  • 服务器性能监控:GET、DELETE、INCR、DECR、CAS等常用操作命中率实时监控

  • 支持数据遍历,方便对存储内容进行监视

  • 支持条件查询,筛选出满足条件的KEY或VALUE

  • 数组、JSON等序列化字符反序列显示

  • 兼容memcache协议的其他服务,如Tokyo Tyrant (遍历功能除外)

  • 支持服务器连接池,多服务器管理切换方便简洁

[root@www ~]# unzip memadmin-master.zip
[root@www ~]# cd memadmin-master
[root@www memadmin-master]# ls
[root@www memadmin-master]# vi config.php    #查看配置文件
<?php
if (!defined('IN_MADM')) exit();

$config['user'] = "admin"; // your username         #默认用户名admin
$config['passwd'] = "admin"; // your password       #默认密码admin
[root@www memadmin-master]# cd ..
[root@www ~]# mv memadmin-master /www/a.com         #应该放到php-fpm服务器上,不能放在nginx服务器上,否则会响应影响

下面我们来登录一下:

a1

连接memcached服务器并演示:

注,修改memcached服务器的IP与端口,我这里是192.168.11.202,端口是默认11211。

a2

注,点击 “高级参数”,选择 “持久化连接”,我这里设置是30s。最后,点击增加按钮。

a3

注,点击默认连接,就可以看到我们设置的参数,点击“开始管理”,进入管理界面。

a4

注,进入管理界面。进入的第一个页面是“连接参数”页面。由于memadmin工具使用简单,我在这里就不详细讲解了。大家自己看一下!

a5


十一、Nginx整合memcached

        nginx的memcached_module模块可以直接从memcached服务器中读取内容后输出,后续的请求不再经过应用程序处理,如php-fpm、django,大大的提升动态页面的速度。nginx只负责从memcached服务器中读取数据,要往memcached写入数据还得需要后台的应用程序来完成,主动的将要缓存的页面缓存到memcached中,可以通过404重定向到后端去处理的。    
ngx_http_memcached_module可以操作任何兼用memcached协议的软件。如ttserver、membase等。

结构图如下:

memcached

memcached的key可以通过memcached_key变量来设置,如以$uri。如果命中,那么直接输出内容,没有命中就意味着nginx需要从应用程序请求页面。同时,我们还希望该应用程序将键值对写入到memcached,以便下一个请求可以直接从memcached获取。如果键值不存在,nginx将报告not found错误。最好的方法是使用error_page指定和location请求处理。同时包含”Bad Gateway”错误和”Gateway Timeout”错误,如:error_page 404 502 504 = @app;。注意:需要设置default_type,否则可能会显示不正常。

1、nginx整合memcache

server {
     location / {

                   set $memcached_key "$uri?$args";     
                memcached_pass     192.168.100.173:11211;
               # default_type       text/html;
                error_page         404 @fallback;    #调用一个叫fallback的location
        }

        location @fallback {                        #定义一个叫fallback的location
                proxy_pass     
        }
}

从上面的配置文件我们可以看出,一个请求到达后,会其uri作为key去Memcached服务器192.168.18.202:11211上查找value,如果没有命中,则返回404。这时通过error_page将404接收转到@fallback,返回给Web服务去处理请求。

2、模块说明

  • memcached_bind    
    语法: memcached_bind address | off;     
    默认值: none     
    配置段: http, server, location     
    指定从哪个IP来连接memcached服务器

  • memcached_buffer_size    
    语法: memcached_buffer_size size;     
    默认值: 4k|8k;     
    配置段: http, server, location     
    读取从memcached服务器接收到响应的缓冲大小。尽快的将响应同步传给客户端。

  • memcached_connect_timeout    
    语法:memcached_connect_timeout time;     
    默认值:60s;     
    配置段:http, server, location     
    与memcached服务器建立连接的超时时间。通常不超过75s。

  • memcached_gzip_flag    
    语法:memcached_gzip_flag flag;     
    默认值:none     
    配置段:http, server, location     
    测试memcached服务器响应标志。如果设置了,将在响应头部添加了Content-Encoding:gzip。

  • memcached_next_upstream    
    语法: memcached_next_upstream error | timeout | invalid_response | not_found | off …;     
    默认值: error timeout;     
    配置段: http, server, location     
    指定在哪些状态下请求将转发到另外的负载均衡服务器上,仅当memcached_pass有两个或两个以上时使用。

  • memcached_pass    
    语法:memcached_pass address:port or socket;     
    默认值:none     
    配置段:location, if in location     
    指定memcached服务器地址。使用变量$memcached_key为key查询值,如果没有相应的值则返回error_page 404。

  • memcached_read_timeout    
    语法:memcached_read_timeout time;     
    默认值:60s;     
    配置段:http, server, location     
    定义从memcached服务器读取响应超时时间。

  • memcached_send_timeout    
    语法:memcached_send_timeout     
    默认值:60s     
    配置段:http, server, location     
    设置发送请求到memcached服务器的超时时间。

用法:$memcached_key变量:memcached key的值。

4.nginx memcached的增强版ngx_http_enhanced_memcached_module

基于nginx memcached 模块的,添加的新特性有:

  • 自定义HTTP头,如Content-Type, Last-Modified。

  • hash键可超过250个字符,memcached受限。

  • 通过HTTP请求将数据存储到memcached。

  • 通过HTTP请求从memcached删除数据。

  • 通过HTTP请求清除所有memcached缓存数据。

  • 通过HTTP请求获取memcached状态数据。

  • 键名空间管理,来部分刷新缓存。

  • 缓存通过If-Modified-Since头和内容Last-Modified来回复304Not Modified请求。


你可能感兴趣的:(memcached)