Linux运维 第三阶段 (十七) memcached

Linux运维 第三阶段 (十七) memcached

 

一、相关概念:

memcached.orglive journal站点贡献的),很多流行站点都在用,如wikipediatwitteryoutubemixi等,memcached是非常流行的缓存服务,众多的应用程序开发基本都支持memcached缓存(CC库,C++C++库,phpphp库,开发时都可直接调用memcached功能,若某个应用程序开发时不用memcached,它就不能往memcached中缓存数据,缓存数据与否取决于app自身,由app决定缓不缓存用不用它)

memcached(键值对key:value server),它只适合存储key:value的数据,而且是缓存cache不是存储storemysqlstore,数据存储下来关机是没事的)

 

若将http中的web object缓存到memcached中,相应的key应如何存,每个web object都通过uri获取,如http://www.magedu.com/index.html,这个web object是唯一的,就将这个uriindex.html)当作key,而文件中的内容作为value

memcachedC/S架构的程序,tcp|udptcp支持长连接,每次从缓存中获取数据要三次握手很浪费时间;若server对性能要求高使用udp),无论tcp|udp都要基于IP报文发送,memcached会监听在某个socket上,否则无法接收client请求

tcp|udpport11211,由libevent提供event-driven功能的库文件

 

ftp servicehttpd service之间区别(clientserver端交互):

协议的不同获取资源的方式不一样;使用独有的协议实现clientserver的交互;

client发命令过去,server要接收并理解这个命令并做出处理,例如http报文,clientGET+URI),server理解GET并将资源响应给client,或clientPUT+FILE),server端先接收指令PUT并将文件存储下来;这些PUTGET就是操作命令,例如ftp中的操作命令(putgetmputmget等);

ftphttp这些协议所使用的命令都很简单,基于文件命令的简单协议simple protocolhttp:textftp:text,binary),若想使用复杂命令(例如用get获取server上某个文件而且要查询文件对应的时间是否正确,否则就不要)是不能达到这样的要求的

memcachedclientserver的交互就是上面这种方式(simplep rotocol),整个处理机制非常简单,在其协议的实施上默认也是基于simple protocol,封装任何指令不使用xml格式

注:两台计算机之间为了交互数据,为能让对方更能理解请求的命令是什么,使用xml格式封装指令,如集群,大多数配置文件是xml格式的,就为实现某些数据交互,避免对方误解,这种协议它所支持的功能及配置非常强大,但xml本身要能解析xml的文档,任何一个协议若支持xml格式传输数据的话,那clientserver都要有一个xml引擎,至少要能分析xml文档,这将导致server复杂,而memcached本身就是为了高性能而存在的,所以越简单越好,因此memcached仅支持一些简单的命令,如get(获取一个key对应的value)、set(设定,保存缓存)

 

作为memcached,往它上面存key:value的数据,编码格式:

text,使用文本格式,整个处理机制将简单很多,还可用#telnet localhost 11211进行测试;

binary,二进制格式,在安全性、效率上要好得多,使用这种格式就要用到专用客户端工具,例如ftp client工具(既支持text又支持binary,如果默认是binary就只能使用专用客户端工具),只有客户端工具才能理解传输的内容,封装数据并传输,接收数据并还原

memcached早期使用text方式(基于text发送指令),现在支持两种格式(text|binary,发送指令,实现数据的上传(将数据放入缓存)下载(从缓存获取数据))

 

memcached是一个缓存服务器,但本身无法决定缓存任何数据,这意味着一半依赖于client-side,一半依赖于server-side,存储是由memacached server负责并提供检索能力,至于怎么存储、存多长时间(过期时间)、谁来存储是由client决定的(client要自己提供key名,标志位、缓存时长、value

例如:set  key  5 6  hello

 

memcached缓存管理工作在lazy模型下(只要系统上有足够空间可用,无论缓存数据有无过期都不会清理,只有没空间使用的情形下才清理),惰性的清理机制,同时又是LRU的清理机制(last recently use,最近最少使用)

若缓存空间过小,但缓存的数据量很大,这样导致缓存抖动很厉害(存了清,清了存,很少命中)

由于存了很多数据,因管理不善或空间过小,导致雪崩效果(表现为缓存数据很多,但就是命中不了)

 

memcached既然是缓存服务器,它并不保证数据持久存储(它假设自己坏了无所谓,它坏了,除影响业务本身访问速度变慢外,是不影响数据本身的),它尽可能实现用内存来缓存数据(内存缓存server),单个对象大小(下限48byte,上限1M

 

memcached在内存中是如何管理缓存的数据,为了存储数据对象,要在内存开辟一段区域(内存中的数据都是按字节序列化的),一个byte一个byte的存,每一个byte都是编址的单元,使用时是按页来用,要能在内存中标记起始地址和结束地址,若失效这段空间要腾出来,这样存储大小不一的对象,存一个删一个,时间久了会有碎片,内存中到处是缝隙,缝隙多了内存要高效利用将很困难(如存一个数据,半天找不到空闲的地方),要反复的完成内存的申请、释放,尤其当存储百万个缓存对象时,这种建立、释放本身要消耗大量的时间,内存碎片将导致进程运行起来会非常慢,刚开始问题不大,运行越久越会拖慢速度,而我们用memcached是用来加速的

 

对于以上问题,如何用高效的机制解决内存的建立和释放,linux内核有两种机制来管理避免内存碎片(buddy system伙伴系统;slab allocatorslab分配器)

buddy system(避免内存外碎片,它实现在整个内存当中以页面的方式管理内存时,有足够的连续的空间可用;在x86x86_64server上,通常是4K大小一个页面,这就意味着,一个进程存第一个对象时,若这个对象8K要用2个页面,这个对象16K要用到4个页面,这样时间长了会有内存页碎片,若之后需要10M的连续空间,由于内存全是缝隙将找不到,为避免这种情况,buddy system就是解决将临近的空闲的内存页面合并为一个大的连续空间,将来申请时可以从一头开始,而不用从中间申请,这将避免页碎片)

注:有些数据存储时占用不了一个页面,例如内核在打开文件时,每一个inode结构(包括inode及元数据各种属性)仅占128byte左右的空间,若直接使用一个页面存那就太浪费空间了,使用slab allocator解决

slab allocator(避免内存内碎片,将要存储数据的大小小于页面单位的(非常小的内存数据结构),给它事先分配好这些结构,随时等待有需求的进程或要存储的对象使用,而且使用结束后不再销毁,随时重复利用,若不够用时再找一个空闲页面立即划分好,这样在使用时不用申请直接用已划分好的;OS上有众多的数据结构都需要这种方式实现,而且存储空间大小也各不相同,如每个进程都有进程描述符(进程号、进程名、属主、属组等信息)空间占约256byte、打开文件时的inode结构占约128byte,这样slab allocator为每一种数据结构都准备一些空间在那放着,任何时候申请直接使用已划分好的,用完后重新放在可用列表中(归类到空闲列表中),所以slab allocator将整个内存中的数据结构分成了已用的和空闲的,在内核中它使用一个数据结构追踪某个slab对象占据的有几个页面(大对象可分多个页面,小对象在一个页面中再次划分),哪个页面是空闲的,依次第一个页面用完了再用第二个,若之后第一个有空闲就在第一个上放数据,达到重复利用的目的

 

一旦给memcached指定有多大内存空间可用后,它会在可用的物理内存空间中申请过来,并且划分好存储空间,分好一个个的slab chunk,每一次缓存数据,找到最佳slab class,若指定的内存空间存满了就要清理了(根据LRU算法),没有存满就算过期了也不清理(lazy模型)

 

例如给memcached指定512M内存,服务在启动时会在内存中划分512M区域开始分片,分片时它会考虑到各种数据大小的存储,例如48byte分一堆,80byte的分一堆,200byte的再分一堆,这每一个类别叫slab类(slab class),每一slab class中都有很多块用来存数据,每一块叫slab chunk,之后要存数据,它会找一个最适合的大小的区域单元来存放,这每一类间隔越小则空间的浪费越少(但类别过多管理也会麻烦),例如要存20byte的数据,它会自动找到48byte这个slab class存(虽然它仅占20byte,另28byte空间就浪费了,为使内存高效管理此处浪费不可避免);早期memcached类别之间是呈2倍增长趋势的,这种管理方式粗糙,浪费的空间大,现在支持使用增长因子来定义(growth factor,在每个类别上定义,每次在上次的基础上往上涨多少),增长因子一般是在12之间的数,例如有一类是48byte定义growth factor2,则下一个是96,若growth factor定义为1.1,则下一个是48*1.1

 

memcached是不通信的分布式缓存服务器(它本身不支持高可用,但分布式功能是它的强项,分布式算法是在app-server上实现的),例如有两台memcached-server,前端app-server若轮流使用memcached,该怎么轮并不取决于这两台memcached-server(这两个memcached彼此间不通信,不需监控对方心跳等),而是用前端的app-server实现(memcached是否在线,上传数据等)

注:若是小规模应用完全可在app-server上实现调度;若大规模,则使用调度器(LVSnginxhaproxy)加持久连接实现

 

memcached键值对key:value存储时,如对keyhash运算除以memcached-server总数再取余,就可定位到是用哪台memcached-server存储,这种算法有很大缺陷(弊端),例如若4memcached中有其中一台挂了或者又新增了一台,之前是除以4,现在除以3,结果导致查询缓存不会定位到之前的那台memcached-server上,所以大量缓存失效要重新建立

consistency hash(一致性哈希算法):client使用,例如一个环中有n个点位(散列的很多挨着的点),这些点0-2^32,有几台memcached-server就将其对应的放在环中的某个点上(例如有4台,2^32除以4),缓存数据时,仍取离散的值,对keyhash运算除以2^32取余,这个值会分散在环中某个点上,按顺时针找最近的一台server存储要缓存的数据,若某一server挂了或增加了一台,则只影响环中某一段中的缓存(增加或减少server只影响局部,之前的算法会影响到全部),使用这种算法将影响范围降到最低

wKioL1aPqOSQoIATAABtwwXo0Xs274.jpg

 

以下是在LNMP架构中提到的memcached

memcached(两个功能:实现缓存后端DB-server的查询结果,提供给多个app-server使用;缓存app-serversession信息):

它本身只是个提供缓存功能的server,到底缓不缓存,谁来缓存,怎么缓存,缓存过期时间,缓存清除等它自身不管,它可以根据你的请求,替你做出决策,例如,app-server查询DB,觉的这个结果可以缓存,由app-server自己把数据放至memcaced 上,当app-server下次找数据时就自动去memcached上去找,memcached是个公共缓存,可被多个node共同使用,若命中率达到40%,对系统性能的提升非常明显

 

若是电商站点,后端某个app-server挂了,每一个app-server为了维持某个用户的购物车、http等会话信息会结合cookieapp-server本地内存中要维护一个session,每一个client只要连接,在app-server上都有session信息,若某个用户第一次连接在app-server5上,第二次被分配到了app-server1上,那之前的会话信息就没了,为使会话继续使用,可用持久连接(同一client的请求始终定位至同一个app-server上,虽会破坏LB效果,但能实现),但要是app-server5挂掉,用户一刷新同样会定位到其它app-server上,会话也照样没了,如果用户请求有5万个,某一个app-server挂掉将会丢失1万个session信息(很可怕)

注:session信息是保存在当前某一个app-server上的本地内存中一份,而且在FS上也会保存一份,方便以后读取,所以只能被这一个主机所使用

 

如果app-server建成集群,session信息在内存中可完成同步,如用户请求app-server1app-server1在建立会话以后,直接通过高可用集群同步至任一node的内存中去,这将有额外的开销(每一个app-server都要通过组播发送出去),若app-server很多每一次这样同步数据量会很大,在小规模场景中勉强可用,但大规模场景就不理想了

 

这时要在各app-server间共享session,使用一个公共区域来保存session信息,让每一个app-server都到这个公共区域中去读会话信息,memcached正是这么一个公共缓存

当某一用户请求第一次被发到app-server1上时,app-server1发现需要为这个请求建立会话,这个会话数据不再保存在本地,直接保存到memcached中,之后哪怕这个用户的请求被转至app-server2上,app-server2会根据用户的cookie信息自动地去memcached中找session信息,把session读过来与用户建立会话,于是本地就有,不过这时风险更大,若memcached挂了,那所有会话都没了,想到为memcached做高可用,memcached本身并不支持高可用,但若做成高可用了也并不理想(它会这样假设,你保存在我这的都是缓存数据,是非关键性数据,是读取的原始数据,我这里的数据就算丢了,你无非是重建而已,我这里不会使用高可用的),但它可很好的实现分布式的功能(memcached的强项),这就意味着1memcached不够用可用多个memcached,如有3memcachedapp-server在存数据时会选一个来存,查找时通过某种算法(例如将用户的cookiehash运算再除以3取余,hash运算的结果相同除3取余的结果就相同)再定位至这个memcached-server

注:若把memcached做成HA-server,意义并不大也不理想(因为缓存数据是在内存中,除非解决两个进程间通过内存将某一node的缓存通知给另一node

 

这样memcached不仅可以缓存DB中查询的数据,还能缓存session信息,所以有人把memcached称万金油(银蛋),它能应付各种情况和场景,只要数据可缓存且缓存的是可序列化的数据(如string、各object等,网络上传输的是01代码,若发一张图片或其它对象最终都可被抽成一根线,再通过网络发送,接收端接收下来将其合并并还原即可)它都能缓存下来,不能序列化就无法在内存中存储,就更不用说发送了

缓存方法就是在内存中开辟一段很小的区域,每个缓存对象将占用一个小区域将数据缓存下来

 

若缓存了有1KW个数据,之后要怎么找,若要遍历这1000W个对象那也太慢了,memcached是键值存储(key:value),在存储时首先给这个数据创建个查找键key,然后再存储它的值valuekey:value存储通常都是基于hash方式,每存一个数据时这个key也需要地方存储,key存储在叫做hash bucket桶中(hash bucket有多个),key存在哪一桶个中是根据hash函数计算得出的,每个桶中比如规定只存100key,将来要找某一个key时做hash运算(hash函数),运算完后就知道在哪个hash bucket中,找到这个桶后,桶中数据相对就很少了,在hash bucket中迅速的做下字符串比较(二次计算)立即找出键,基于这种方式查找速度是无与伦比的快(hash索引非常快,所以查找都是O1)的),这样1000个键无非是在某个桶中找一次,1000万个键无非是找出在哪一个桶中

但存储太多个对象也不好,每存储一个数据都要开辟一小段内存,不同的场景所需要的空间也不一样,对象多了导致内存碎片化,在内存中的这些对象要被管理(如对象过期要回收等),要有很好的内存管理策略(策略即算法,通过程序不定期的去执行,执行就要消耗CPU时间,会有额外开销),当对象少时没什么问题,但对象超多,内存随时都要释放和回收、分配,这是不小的工作量,所以并不建议在memcached中缓存过多的数据

 

memcached缓存时支持的单个对象最大1M空间,最小48byte

memcacheC/S架构,client就是app-server,应用程序通过协议把数据通过网络传送给memcached-servermemcached根据client的请求将数据缓存下来,所以client可向server-side发送不同指令,如建立缓存、清除缓存、在缓存中附加新数据等有很多命令

 

 

二、操作(1memcached安装;2、常用命令;3、安装php的扩展memcache4nginx整合memcached5phpsession保存在memcached中;6、使用web界面管理工具memadmin):

环境:

[root@node1 ~]# uname -a

Linux node1.magedu.com 2.6.32-358.el6.x86_64#1 SMP Tue Jan 29 11:47:41 EST 2013 x86_64 x86_64 x86_64 GNU/Linux

准备安装包及yum源:

libevent-2.0.22-stable.tar.gz

memcached-1.4.25.tar.gz

memcache-2.2.7.tgz

memadmin-1.0.12.tar.gz

注:在LNMP环境上操作(LNMP环境搭建参照《Linux运维第三阶段(十五)理解LNMP

 

 

1、安装

[root@node1 ~]# yum -y groupinstall “Desktop Platform” “Desktop Platform Development” "Server Platform Development" “Development tools” “Compatibility libraries”(确保这几个底层依赖包已安装)

[root@node1 ~]# rpm -q libevent(此版本在memcached源码编译时过不去,得安装2.0.22版本,2.0比自带的glibc库性能要高很多,对于高并发的程序它们运行时会自动使用libevent库)

libevent-1.4.13-4.el6.x86_64

[root@node1 ~]# rpm -q cyrus-sasl-devel(认证相关,确保已安装)

cyrus-sasl-devel-2.1.23-13.el6_3.1.x86_64

 

[root@node1 ~]# tar xf libevent-2.0.22-stable.tar.gz

[root@node1 ~]# cd libevent-2.0.22-stable

[root@node1 libevent-2.0.22-stable]#./configure --prefix=/usr/local/libevent

[root@node1 libevent-2.0.22-stable]# make && make install

[root@node1 libevent-2.0.22-stable]# cd

[root@node1 ~]# echo "/usr/local/libevent/lib" > /etc/ld.so.conf.d/libevent.conf

[root@node1 ~]# ldconfig -v

[root@node1 ~]# ln -sv /usr/local/libevent/include/ /usr/include/libevent

"/usr/include/libevent" ->"/usr/local/libevent/include/"

 

[root@node1 ~]# tar xf memcached-1.4.25.tar.gz

[root@node1 ~]# cd memcached-1.4.25

[root@node1 memcached-1.4.25]# ./configure --help

[root@node1 memcached-1.4.25]# ./configure --prefix=/usr/local/memcached --enable-sasl --with-libevent=/usr/local/libevent

[root@node1 memcached-1.4.25]# make && make install

 

[root@node1 memcached-1.4.25]# cd /usr/local/memcached/

[root@node1 memcached]# ls bin

memcached

[root@node1 memcached]# echo "export PATH=$PATH:/usr/local/memcached/bin/" > /etc/profile.d/memcached.sh

[root@node1 memcached]# . !$

. /etc/profile.d/memcached.sh

[root@node1 memcached]# cd

[root@node1 ~]# memcached -h(类似mysql-proxy,支持很多选项)

-m NUM(以M为单位指定最大可用内存空间,max memory to use for items in megabytes (default: 64 MB)

-n BYTES(指定最小存储块是多大slab chunk,增长因子就是在此基础上增加的,minimum space allocated for key+value+flags (default: 48)

-f FACTOR_NUM(指定增长因子grown factor,一般1-2之间的数,chunk size growth factor (default: 1.25)

-vvvery verbose (also print client commands/reponses)

-u USERNAMEassume identity of <username> (only when run as root)

-drun as a daemon

-p NUMTCP port number to listen on (default: 11211)

-U NUMUDP port number to listen on (default: 11211, 0 is off)

-l ADDRESSinterface to listen on (default: INADDR_ANY, all addresses)

-S(启用sasl认证,Turn on Sasl authentication

-s FILE(指定socket,类似mysql/tmp/mysql.sock本地套接字的通信机制,能利用近似共享内存的方式通信,UNIX socket path to listen on (disables network support)

-rmaximize core file limit

-c NUM(最大并发连接数,max simultaneous connections (default: 1024)

-t NUM(用于处理入站请求的最大线程数,仅在memcached编译时开启支持线程才有效(linux对线程支持有限)number of threads to use (default: 4)

-P FILEsave PID in <file>, only used with -d option

-L(试图使用最多的内存空间,Try touse large memory pages (if available)

-CDisable use of CAS

-b NUMSet the backlog queue limit (default: 1024)

-o(指定额外选项,Comma separated list of extended or experimental options

 

[root@node1 ~]# memcached -m 64 -n 20 -f 1.1 -vv -u nobody -d(可看出具体分配空间过程)

[root@node1 ~]# slab class   1: chunk size        72 perslab   14563

slab class  2: chunk size        80perslab   13107

slab class  3: chunk size        88perslab   11915

slab class  4: chunk size        96perslab   10922

slab class  5: chunk size       112perslab    9362

slab class  6: chunk size       128perslab    8192

slab class  7: chunk size       144perslab    7281

slab class  8: chunk size       160 perslab    6553

……

[root@node1 ~]# netstat -tnupl | grep :11211

tcp       0      0 0.0.0.0:11211               0.0.0.0:*                   LISTEN      3957/memcached     

tcp       0      0 :::11211                    :::*                        LISTEN      3957/memcached     

udp       0      0 0.0.0.0:11211               0.0.0.0:*                               3957/memcached     

udp       0      0 :::11211                    :::*                                   3957/memcached    

[root@node1 ~]# killall memcached

[root@node1 ~]# ps aux |grep memcached |grep -v grep

[root@node1 ~]# vim /etc/init.d/memcached(为memcached提供sysv风格启动脚本,此脚本内容见文末附)

[root@node1 ~]# vim /etc/sysconfig/memcached(并为脚本提供配置文件,方便各配置选项的更改)

CACHESIZE="64"

BYTES="48"

FACTOR="1.25"

USER="nobody"

PORT="11211"

MAXCONN="1024"

OPTIONS=""

[root@node1 ~]# chmod +x !$

chmod +x /etc/init.d/memcached

[root@node1 ~]# chkconfig --add memcached

[root@node1 ~]# service memcached start

Starting Distributed memory caching(memcached):           [确定]

 

 

2、常用命令:

memcached支持的命令(在telnet下使用,因为memcached没有客户端工具,只能在telnet下直接交互):

syntax格式:

COMMAND_NAME  KEY_NAME FLAGS  EXPIRE_TIME  BYTES

DATA_BLOCK

其中COMMAND_NAME常用的有(set|get|gets|add|replace|delete|cas|stats|statsitems|append|prepend|flush_all|incr|decr);

KEY_NAME(要知道某个key所对应的value值,必须要知道key_name

FLAGS(客户机使用此项存储关于key:value的额外信息)

EXPIRE_TIME(过期时间,0表示永远不过期)

BYTES(存储字节数)

DATA_BLOCK(存放value

 

[root@node1 ~]# telnet localhost 11211

Trying 127.0.0.1...

Connected to localhost.

Escape character is '^]'.

stats(输入此指令可看相关状态)

STAT pid 3957

STAT uptime 255

STAT time 1448113877

STAT version 1.4.25

STAT libevent 2.0.22-stable

STAT pointer_size 64

……

STAT get_hits 0

STAT get_misses 0

STAT delete_misses 0

STAT delete_hits 0

set mykey 0 10 12set使用频率很高,用于如果key不存在,使用set可添加,如果key存在,使用set可更新key相关数据)

hello magedu

STORED

get mykeyget后跟key_name,查看key所对应的value,若要查看多个key用空格隔开)

VALUE mykey 0 12

hello magedu

END

add mykey1 0 0 7add添加,仅在key不存在时才能添加)

jowin

STORED

get mykey1

VALUE mykey1 0 7

jowin

END

set mykey1 0 0 8set更新key所对应的参数及value

chai

STORED

get mykey1

VALUE mykey1 0 8

chai

END

replace mykey1 0 0 8replace替换,仅在key存在时才能使用)

cjowin

STORED

get mykey1

VALUE mykey1 0 8

cjowin

END

delete mykey1(删除,已存在记录和不存在的记录会返回不同的结果)

DELETED

delete mykey2

NOT_FOUND

add mykey 0 0 7

hello

STORED

gets mykeygets返回结果比get返回的结果多了一列,最后一列这个数字(此例中是7)可检查数据是否发生改变,当key对应的value改变时,最后的这个数字也会变化)

VALUE mykey 0 7 7

hello

END

replace mykey 0 0 7

haha

STORED

gets mykey(内容改变时,gets得到的结果中最后一个数字也变了)

VALUE mykey 0 7 8

haha

END

cas mykey 0 0 7 8caschecked and set,只有在此处输入的最后一个数字与gets得到的最后一位数字相同才存储,否则返回exists

hello 

STORED

gets mykey

VALUE mykey 0 7 9

hello

END

cas mykey 0 0 7 18

kao

EXISTS

stats items(列出STAT itmes行,若memcached中存储内容很多会列出很多行)

STAT items:2:number 1

STAT items:2:age 173

STAT items:2:evicted 0

STAT items:2:evicted_nonzero 0

STAT items:2:evicted_time 0

STAT items:2:outofmemory 0

STAT items:2:tailrepairs 0

STAT items:2:reclaimed 0

STAT items:2:expired_unfetched 0

STAT items:2:evicted_unfetched 0

STAT items:2:crawler_reclaimed 0

STAT items:2:crawler_items_checked 0

STAT items:2:lrutail_reflocked 0

END

stats cachedump 2 02stats item返回的值,表示slab_id0表示limit_num代表返回所有记录数;通过stats items,stats cachedump slab_id limit_num,get可遍历memcached的记录)

ITEM mykey [7 b; 1448113562 s]

END

stats cachedump 2 128

ITEM mykey [7 b; 1448113562 s]

END

另还有常用的:stats slabs,stats sizes,stats reset

append(在现有缓存数据后添加缓存数据);prepend(在现有的缓存数据前添加缓存数据);flush_all(默认使已经存在的key:value立即失效,或在指定的时间后,执行这个命令后再用get获取key时将不会有内容返回,之前的key:value在内存中并没有释放(因为是lazy模型及LRU清理机制))

 

 

3、安装php扩展(memcache):

使用某一应用程序(phpmysql)来连接一个服务(memcachedmysqld)时,必须要利用这个服务的客户端库来编程(例如mysql用自己的client连上服务直接发命令,在使用php编程时调用一个库mysql-connect,在函数中传一大堆参数),没法直接调用客户端,只能用客户端库,这就是很多应用程序要提供命令行工具(供用户测试使用)和库(库可供二次开发用)

memcached没有客户端,只是通过#telnet localhost 11211与服务直接交互,作为php程序员(或C程序员)在开发时,要写一个程序能够利用memcached服务器来完成数据缓存以此提高系统性能,必须要针对客户端库来编程,由此必须要为某一种语言提供客户端库,以完成这个程序编程时尽可能简单的利用memcached

 

客户端库有(三种语言perlphpC/C++各自提供的客户端库):

perl moduleperl要使用memcached就用这个perl module):

cache;;memcached

phpphp要使用memcached,得为php安装一个扩展,共提供了两个库(两个扩展)):

memcache

memcached

注:注意这里的memcachememcachedphp的两个库(两个扩展,使用时安装一个即可),memcachedmemcache要先进,支持的功能要强大,一般用memcached

C/C++

libmemcached

 

[root@node1 ~]# vim /etc/nginx/nginx.conf(确保以下段配置就绪)

……

       location / {

           root html;

           index index.php index.html index.htm;

       }

……

       location ~ \.php$ {

           root           html;

           fastcgi_pass   127.0.0.1:9000;

           fastcgi_index  index.php;

           fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;

           include        fastcgi_params;

       }

……

[root@node1 ~]# cat /usr/html/index.php

<?php

phpinfo();

?>

[root@node1 ~]# service nginx start

正在启动 nginx                                           [确定]

[root@node1 ~]# service php-fpm start

Starting php-fpm  done

[root@node1 ~]# netstat -tnlp | grep :9000

tcp       0      0 127.0.0.1:9000              0.0.0.0:*                   LISTEN      4998/php-fpm   

[root@node1 ~]# ps aux | grep -v grep |grep -c php-fpmphp-fpm进程共9个,其中1个主进程,8个子进程,在/usr/local/php/etc/php-fpm.conf配置文件中设置了pm.start_servers= 8

9

wKiom1aPrVbAcEg3AABmjgFnOAE130.jpg

 

[root@node1 ~]# tar xf memcache-2.2.7.tgz

[root@node1 ~]# cd memcache

[root@node1 ~]# cd memcache-2.2.7

[root@node1 memcache-2.2.7]#/usr/local/php/bin/phpize

Configuring for:

PHP Api Version:         20100412

Zend Module Api No:      20100525

Zend Extension Api No:   220100525

[root@node1 memcache-2.2.7]# ./configure --with-php-config=/usr/local/php/bin/php-config --enable-memcache

[root@node1 memcache-2.2.7]# make && make install(记录安装完后最后一行给的目录)

……

Installing shared extensions:    /usr/local/php/lib/php/extensions/no-debug-non-zts-20100525/

 

[root@node1 memcache-2.2.7]# ls /usr/local/php/lib/php/extensions/no-debug-non-zts-20100525/

memcache.so xcache.so

[root@node1 memcache-2.2.7]# vim /etc/php.d/memcache.ini

extension = “/usr/local/php/lib/php/extensions/no-debug-non-zts-20100525/memcache.so”

[root@node1 memcache-2.2.7]# cd

[root@node1 ~]# vim /usr/html/test.php

---------------test pagestart--------------------

<?php

$mem = new Memcache;

$mem->connect("127.0.0.1",11211)  or die("Could notconnect");

 

$version = $mem->getVersion();

echo "Server's version:".$version."<br/>\n";

 

$mem->set('testkey', 'hello magedu', 0,600) or die("Failed to save data at the memcached server");

echo "Store data in the cache (datawill expire in 600 seconds)<br/>\n";

 

$get_result = $mem->get('testkey');

echo "$get_result is from memcachedserver.";        

?>

---------------test pageend------------------

[root@node1 ~]# service php-fpm restart

Gracefully shutting down php-fpm . done

Starting php-fpm  done

 

测试:

wKioL1aPrcCBsCVJAAB0CftQkE8037.jpg

 

wKioL1aPrc-TnTKWAABzAL7jINw134.jpg

[root@node1 ~]# telnet localhost 11211

Trying 127.0.0.1...

Connected to localhost.

Escape character is '^]'.

get testkey

VALUE testkey 0 12

hello magedu

END

 

4nginx整合memcached

注:nginx的缓存是在磁盘上性能不好

[root@node1 ~]# vim /etc/nginx/nginx.conf

server {

       listen       80;

       server_name  localhost;

       root html;

       location / {

            set $memcached_key $uri;

            memcached_pass 127.0.0.1:11211;

            default_type text/html;

            error_page 404 @fallback;

       }

       location @fallback {

           proxy_pass http://192.168.41.135;

       }

}

 

 

5、将phpsession保存在memcached中:

[root@node1 ~]# vim /etc/php.ini(注意Session段中以下几项,session.name按默认,此名字之后在很多地方要用到)

[Session]

session.save_handler = memcache

session.save_path = "tcp://127.0.0.1:11211?persistent=1&weight=1&timeout=1&retry_interval=15"

session.name = PHPSESSID

测试:准备两个测试脚本

[root@node1 ~]# vim /usr/html/setsession.php

--------------test script start-------------

<?php

session_start();

if (!isset($_SESSION['www.MageEdu.com'])) {

     $_SESSION['www.MageEdu.com'] = time();

}

print $_SESSION['www.MageEdu.com'];

print "<br><br>";

print "Session ID: " .session_id();

?>

------------------test script end-------------

[root@node1 ~]# vim /usr/html/showsession.php

---------------test script start--------------

<?php

session_start();

$memcache_obj = new Memcache;

$memcache_obj->connect('127.0.0.1',11211);

$mysess=session_id();

var_dump($memcache_obj->get($mysess));

$memcache_obj->close();

?>

-------------test script end----------------------

wKioL1aPrgnioX9aAABiFo-X-KY471.jpg

wKiom1aPre6QnlK4AABVH_ylETI578.jpg

 

6、使用web界面管理工具memadmin

此工具官网描述:

MemAdmin是一款可视化的Memcached管理与监控工具,基于PHP5&JQuery开发,体积小,操作简单.

MemAdmin主要功能:

服务器参数监控:STATSSETTINGSITEMSSLABSSIZES实时刷新

服务器性能监控:GETDELETEINCRDECRCAS等常用操作命中率实时监控

支持数据遍历,方便对存储内容进行监视支持条件查询,筛选出满足条件的KEYVALUE 数组、JSON等序列化字符反序列显示

兼容memcache协议的其他服务,Tokyo Tyrant (遍历功能除外) 支持服务器连接池,多服务器管理切换方便简洁.

 

[root@node1 ~]# tar xf memadmin-1.0.12.tar.gz

[root@node1 ~]# mv memadmin /usr/html/

[root@node1 ~]# ls /usr/html/memadmin/

apps config.php  images  include index.php  langs  LICENSE.txt README.txt  views

[root@node1 ~]# vim /usr/html/memadmin/config.php(此文件中有账号密码,默认都是admin

 

wKioL1aPrkmDFCGUAABRpMUDqU8797.jpg

wKiom1aPrlqTJfEwAABUBKX6VHI262.jpg

添加服务器连接-->名称:localhosthost127.0.0.1port11211,持久化连接30-->添加-->开始管理


wKiom1aPrqShqo3bAADLB5oss8M886.jpg

wKioL1aPrt7TZ4bwAADYO_wjmgI084.jpg

wKioL1aPrwfyxX0MAACiqXdLDEk674.jpg

wKiom1aPrwbDtZCkAABLYkRXqwA710.jpg

 wKiom1aPry_CmxfKAABStT9JNgI581.jpg

 

附:memcached启动脚本:

--------------script start-----------------

#!/bin/bash

#

# Init file for memcached

#

# chkconfig: - 86 14

# description: Distributed memory cachingdaemon

#

# processname: memcached

# config: /etc/sysconfig/memcached

 

. /etc/rc.d/init.d/functions

 

## Default variables

CACHESIZE="64"

BYTES=”48”

FACTOR=”1.25”

USER="nobody"

PORT="11211"

MAXCONN="1024"

OPTIONS=""

 

[ -f /etc/sysconfig/memcached ] && source /etc/sysconfig/memcached

 

RETVAL=0

prog="/usr/local/memcached/bin/memcached"

desc="Distributed memory caching"

lockfile="/var/lock/subsys/memcached"

 

start() {

       echo -n $"Starting $desc (memcached): "

       daemon $prog -m $CACHESIZE -n $BYTES -f $FACTOR -u $USER -p $PORT -c$MAXCONN -d

       RETVAL=$?

       echo

       [ $RETVAL -eq 0 ] && touch $lockfile

       return $RETVAL

}

 

stop() {

       echo -n $"Shutting down $desc (memcached): "

       killproc $prog

       RETVAL=$?

       echo

       [ $RETVAL -eq 0 ] && rm -f $lockfile

       return $RETVAL

}

 

restart() {

       stop

       start

}

 

reload() {

       echo -n $"Reloading $desc ($prog): "

       killproc $prog -HUP

       RETVAL=$?

       echo

       return $RETVAL

}

 

case "$1" in

 start)

       start

       ;;

 stop)

       stop

       ;;

 restart)

       restart

       ;;

 condrestart)

       [ -e $lockfile ] && restart

       RETVAL=$?

       ;;      

 reload)

       reload

       ;;

 status)

       status $prog

       RETVAL=$?

       ;;

   *)

       echo $"Usage: $0 {start|stop|restart|condrestart|status}"

       RETVAL=1

esac

 

exit $RETVAL

--------------scrip tstop--------------------

 

 

 

 

以上是学习《马哥运维课程》做的笔记。


你可能感兴趣的:(linux,memcached,运维)