Memcachedphp
1、Memcached简介html
Memcached是一个开源的,支持高性能,高并发的分布式内存缓存系统,由C语言编写,总共2000多行代码。从软件名称上看,前3个字符“Mem”就是内存的意思,而接下来的后面5个字符“cache”就是缓存的意思,最后一个字符d,是daemon的意思,表明是服务器端守护进程模式服务。前端
Memcached服务分为服务器端和客户端两部分,其中,服务器端软件的名字形如Memcached-1.4.24.tar.gz,客户端软件的名字形如Memcache-2.25.tar.gznode
Memcached软件诞生于2003年,最初由LiveJournal的Brad Fitzpatrick开发完成。Memcache是整个项目的名称,而Memcached是服务器端的主程序名,因其协议简单,应用部署方便,且支持高并发,所以被互联网企业普遍使用,直到如今仍然如此。其官方网站地址:http://memcached.org/.mysql
Memcached的做用nginx
传统场景中,多数Web应用都将数据保存到关系型数据库中(例如:MySQL),Web服务器从中读取数据并在浏览器中显示。但随着数据量的增大,访问的集中,关系型数据库的负担就会出现加剧,响应缓慢,致使网站打开延迟等问题,影响用户体验。redis
这时就须要Memcached软件出马了。使用Memcached的主要目的是,经过在自身内存中缓存关系型数据库的查询结果,减小数据库被访问的次数,以提升动态Web应用的速度,提升网站架构的并发能力和可扩展性。算法
Memcached服务的运行原理是经过在事先规划好的系统内存空间中临时缓存数据库中的各种数据,以达到减小前端业务服务对数据库的直接高并发访问,从而提高大规模网站集群中动态服务的并发访问能力。
-生产场景的Memcached服务通常被用来保存网站中常常被读取的对象或数据,就像咱们的客户端浏览器也会把常常访问的网页缓存起来同样,经过内存缓存来存取对象或数据要比磁盘存取快不少,由于磁盘是机械的,所以,在当今的IT企业中,Memcached的应用范围很普遍。sql
互联网常见内存缓存服务软件数据库
2、Memcached的用户与应用场景
一、Memcached常见用途工做流程
Memcached是一种内存缓存软件,在工做中常常用来缓存数据库的查询数据,数据被缓存在事先与分配的Memcached管理的内存中,能够经过API或命令的方式存取内存中缓存的这些数据,Memcached服务内存中缓存的数据就像一张巨大的hash表,每条数据都是以key-value对的形式存在。
二、网站读取Memcached数据时工做流程
从逻辑上来讲,当程序访问后端数据库获取数据时会优先访问Memcached缓存,若是缓存中有数据就直接返回给客户端用户,若是没有合适的数据(没有命中),再去后端的数据库读取数据,读取到须要的数据后,就会把数据返回给客户端,同时还会把读取到的数据缓存到Memcached内存中,这样客户端用户再次请求相同的数据时就会直接读取Memcached缓存的数据了,这就大大地减轻了后端数据库的压力,并提升了整个网站的响应速度,提高了用户体验。
如上图所示:使用Memcached缓存查询的数据来减小数据库压力的具体工做流程以下:
(1)Web程序首先检查客户端请求的数据是否在Memcached缓存中存在,若是存在,直接把请求的数据返回给客户端,此时再也不请求后端数据库。
(2)若是请求的数据在Memcached缓存中不存在,则程序会去请求数据库服务,把从数据库中取到的数据返回给客户端,同时把新取到的数据缓存一份到Memcached缓存中。
三、网站更新Memcached数据时的工做流程
具体流程以下:
(1)当程序更新或删除数据时,会首先处理后端数据库中的数据。
(2)在处理后端数据库中数据的同时,也会通知Memcached,告诉它对应的旧数据失效,从而保证Memcached中缓存的数据始终和数据库中一致,这个数据一致性很是重要,也是大型网站分布式缓存集群最头疼的问题所在。
(3)若是是在高并发读写场合,除了要程序通知Memcached过时的缓存失效外,还可能要经过相关机制,例如在数据库上部署相关程序(如在数据库中设置触发器使用UDFs),实现当数据库有更新时就把数据更新到Memcached服务中,这样一来,客户端在访问新数据时,因预先把更新过的数据库数据复制到Memcached中缓存起来了,因此能够减小第一次查询数据库带来的访问压力,提高Memcached中缓存的命中率,甚至新浪门户还会把持久化存储Redis作成MySQL数据库的从库,实现真正的主从复制。
下图为Memcached网站做为缓存应用更新数据的流程
下图为Memcached服务做为缓存应用经过相关软件更新数据的流程
四、Memcached在企业中的应用场景
(1)做为数据库的查询数据缓存
完整数据缓存
例如:电商的商品分类功能不是常常变更的,所以能够事先放到Memcached里,而后再对外提供数据访问。这个过程被称之为“数据预热”。
此时只需读取缓存,无需读取数据库就能获得Memcached缓存里的全部商品分类数据了,因此数据库的访问压力就会大大下降。
为何商品分类数据能够事先放在缓存里呢?
由于,商品分类几乎都是由内部人员管理的,若是须要更新数据,更新数据库后,就能够把数据同时更新到Memcached里。
若是把商品分类数据作成静态化文件,而后,经过在前端Web缓存或者使用CDN加速效果更好。
热点数据缓存
热点数据缓存通常是用于由用户更新的商品,例如淘宝的卖家,在卖家新增商品后,网站程序就会把商品写入后端数据库,同时把这部分数据,放入Memcached内存中,下一次访问这个商品的请求就直接从Memcached内存中取走了。这种方法用来缓存网站热点的数据,即利用Memcached缓存常常被访问的数据。
提示:
这个过程能够经过程序实现,也能够在数据库上安装相关软件进行设置,直接由数据库把内容更新到Memcached中,就至关于Memcached是MySQL的从库同样。
(2)做为集群节点的session会话共享存储
即把客户端用户请求多个前端应用服务集群产生的session会话信息,统一存储到一个Memcached缓存中。因为session会话数据是存储在内存中的,因此速度很快。
下图为Memcached服务在企业集群架构中的常见工做位置:
3、Memcached的特色与工做机制
一、Memcached的特色
benet-->36,key=benet,value=36 yunjisuan-->28,key=yunjisuan,value=28 #经过benet key能够获取到36值,同理经过yunjisuan key能够获取28值
下面是利用Web端程序实现Memcached分布式的简单代码:
"memcached_servers" ==>array( '10.4.4.4:11211', '10.4.4.5:11211', '10.4.4.6:11211',
下面使用Tengine反向代理负载均衡的一致性哈希算法实现分布式Memcached的配置。
http { upstream test { consistent_hash $request_uri; server 127.0.0.1:11211 id=1001 weight=3; server 127.0.0.1:11212 id=1002 weight=10; server 127.0.0.1:11213 id=1003 weight=20; } }
提示:
Tengine是淘宝网开源的Nginx的分支,上述代码来自:
http://tengine.taobao.org/document_cn/http_upstream_consistent_hash_cn.html
二、Memcached工做原理与机制
(1)Memcached工做原理
Memcached是一套相似C/S模式架构的软件,在服务器端启动Memcached服务守护进程,能够指定监听本地的IP地址,端口号,并发访问链接数,以及分配了多少内存来处理客户端请求。
(2)Socket时间处理机制
Memcached软件是由C语言来实现的,所有代码仅有2000多行,采用的是异步epoll/kqueue非阻塞I/O网络模型,其实现方式是基于异步的libevent事件单进程,单线程模式。使用libevent做为事件通知机制,应用程序端经过指定服务器的IP地址及端口,就能够链接Memcached服务进行通讯。
(3)数据存储机制
须要被缓存的数据以key/value键值对的形式保存在服务器端预分配的内存区中,每一个被缓存的数据都有惟一的标识key,操做Memcached中的数据就是经过这个惟一标识的key进行的。缓存到Memcached中的数据仅放置在Memcached服务预分配的内存中,而非存储在Memcached服务器所在的磁盘上,所以存取速度很是快。
因为Memcached服务自身没有对缓存的数据进行持久化存储的涉及,所以,在服务器端的Memcached服务进程重启以后,存储在内存中的这些数据就会丢失。且当内存中缓存的数据容量达到启动时设定的内存值时,也会自动使用LRU算法删除过时的数据。
开发Memcached的初衷仅是经过内存缓存提高访问效率,并无过多考虑数据的永久存储问题。所以,若是使用Memcached做为缓存数据服务,要考虑数据丢失后带来的问题,例如:是否能够从新生成数据,还有,在高并发场合下缓存宕机或重启会不会致使大量请求直接到数据库,致使数据库没法承受,最终致使网站架构雪崩等。
(4)内存管理机制
Memcached采用了以下机制:
(5)多线程处理机制
多线程处理时采用的是pthread(POSIX)线程模式。
若要激活多线程,可在编译时指定:./configure --enable-threads
锁机制不够完善
负载太重时,能够开启多线程(-t 线程数为CPU核数)
三、Memcached预热理念及集群节点的正确重启方法
Memcached预热理念
当须要大面积重启Memcached时,首先要在前端控制网站入口的访问流量,而后,重启Memcached集群并进行数据预热,全部数据都预热完毕以后,再逐步放开前端网站入口的流量。
为了知足Memcached服务数据能够持久化存储的需求,在较早时期,新浪网基于Memcached服务开发了一款NoSQL软件,名字为MemcacheDB,实现了在缓存的基础上增长了持久存储的特性,不过目前逐步被更优秀的Redis软件取代了。
正确开启网站集群服务器
若是因为机房断电或者搬迁服务器集群到新机房,那么启动集群服务器时,必定要从网站集群的后端依次往前端开启,特别是开启Memcached缓存服务器时要提早预热。
4、Memcached内存管理
一、Memcached内存管理机制解析
(1)malloc内存管理机制
在讲解Memcached内存管理机制前,先来了解malloc
malloc的全称是memory allocation,中文名称动态内存分配,当没法知道内存具体位置的时候,想要绑定真正的内存空间,就须要用到动态分配内存。
早期的Memcached内存管理是经过malloc分配的内存实现的1,使用完后经过free来回收内存。这种方式容易产生内存碎片并下降操做系统对内存的管理效率。所以,也会加剧操做系统内存管理器的负担,最坏的状况下,会致使操做系统比Memcached进程自己还慢,为了解决上述问题,Slab Allocator内存分配机制就诞生了。
(2)Slab内存管理机制
如今的Memcached是利用Slab Allocation机制来分配和管理内存的,过程以下:
1)提早将大内存分配大小为1MB的若干个slab,而后针对每一个slab再进行小对象填充,这个小对象称为chunk,避免大量重复的初始化和清理,减轻了内存管理器的负担。
Slab Allocation内存分配的原理是按照预先规定的大小,将分配给Memcached服务的内存预先分割成特定长度的内存块(chunk),再把尺寸相同的内存块(chunk)分红组(chunks slab class),这些内存块不会释放,能够重复利用,以下图所示。
2)新增数据对象存储时。因Memcached服务器中保存着slab内空闲chunk的列表,他会根据该列表选择chunk,而后将数据缓存于其中。当有数据存入时,Memcached根据接收到的数据大小,选择最适合数据大小的slab分配一个能存下这个数据的最小内存块(chunk)。例如:有100字节的一个数据,就会被分配存入下面112字节的一个内存块中,这样会有12字节被浪费,这部分空间就不能被使用了,这也是Slab Allocator机制的一个缺点。
Slab Allocator还可重复使用已分配的内存,即分配到的内存不释放,而是重复利用。
(3)Slab Allocation的主要术语
(4)Slab内存管理机制特色
提早分配大内存Slab 1MB,再进行小对象填充chunk。
避免大量重复的初始化和清理,减轻内存管理器负担。
避免频繁malloc/free内存分配致使的碎片
Mc内存管理机制小结
Mc的早期内存管理机制为malloc(动态内存分配)
malloc(动态内存分配)产生内存碎片,致使操做系统性能急剧降低。
Slab内存分配机制能够解决内存碎片的问题
Memcached服务的内存预先分割成特定长度的内存块,称为chunk,用于缓存数据的内存空间或内存块,至关于磁盘的block,只不过磁盘的每个block都是相等的,而chunk只有在同一个Slab Class内才是相等的。
Slab Class指特定大小(1MB)的包含多个chunk的集合或组,一个Memcached包含多个Slab Class,每一个Slab Class包含多个相同大小的chunk。
Slab机制也有缺点,例如,Chunk的空间会有浪费等。
二、Memcached Slab Allocator内存管理机制的缺点
(1)chunk存储item浪费空间
Slab Allocator解决了当初的内存碎片问题,但新的机制也给Memcached带来了新的问题。这个问题就是,因为分配的是特定长度的内存,所以没法有效利用分配的内存。例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了,以下图所示:
避免浪费内存的办法是,预先计算出应用存入的数据大小,或把同一业务类型的数据存入一个Memcached服务器中,确保存入的数据大小相对均匀,这样就能够减小内存的浪费。
还有一种办法是,在启动时指定“-f”参数,能在某种程度上控制内存组之间的大小差别。在应用中使用Memcached时,一般能够不从新设置这个参数,即便用默认值1.25进行部署便可。若是想优化Memcached对内存的使用,能够考虑从新计算数据的预期平均长度,调整这个参数来得到合适的设置值,命令以下:
-f <factor>chunk size growth factor (default:1.25)!
(2)Slab尾部剩余空间
假设在classid=40中,两个chunk占用了1009384byte,那么就有1048576-1009384=39192byte会被浪费掉。解决办法:规划slab大小=chunk大小*n整数倍。
三、使用Growth Factor对Slab Allocator内存管理机制调优
在启动Memcached时指定Growth Factor因子(经过 -f 选项),就能够在某种程度上控制每组Slab之间的差别。默认值1.25。可是,在该选项出现以前,这个因子曾经被固定为2,称为2“powers of 2”策略。让咱们用之前的设置,以verbose模式启动Memcached试试看:
memcached -f 2 w
启动后的verbose
slab class 1:chunk size 128 perslab 8192 slab class 2:chunk size 256 perslab 4096 slab class 3:chunk size 512 perslab 2048 slab class 4:chunk size 1024 perslab 1024 slab class 5:chunk size 2048 perslab 512 slab class 6:chunk size 4096 perslab 256 slab class 7:chunk size 8192 perslab 128 slab class 8:chunk size 16384 perslab 64 slab class 9:chunk size 32768 perslab 32 slab class 10:chunk size 65536 perslab 16 slab class 11:chunk size 131072 perslab 8 slab class 12:chunk size 262144 perslab 4 slab class 13:chunk size 524288 perslab 2
可见,从128字节的组开始,组的大小依次增大为原来的2倍。这样设置的问题是,Slab之间的差异比较大,有些状况下就至关浪费内存。所以,为尽可能减小内存浪费,两年前追加了growth factor这个选项。
来看看如今的默认设置(f=1.25)时的输出:
slab class 1:chunk size 88 perslab 11915 <---88*11915=1048520 slab class 2:chunk size 112 perslab 9362 slab class 3:chunk size 144 perslab 7281 slab class 4:chunk size 184 perslab 5698 slab class 5:chunk size 232 perslab 4519 slab class 6:chunk size 296 perslab 3542 slab class 7:chunk size 376 perslab 2788 slab class 8:chunk size 472 perslab 2221 slab class 9:chunk size 592 perslab 1771 slab class 10:chunk size 744 perslab 1409 <---744*1409=1048520
此时每一个Slab的大小是同样的,即1048520,1MB。组间的差距比因子为2时小得多,可见,这个值越小,Slab中chunk size的差距就越小,内存浪费也就越小。可见,默认值1.25更适合缓存几百字节的对象。从上面的输出结果来看,可能会以为有些计算偏差,这些偏差是为了保持字节数的对齐而故意设置的。
当使用Memcached或是直接使用默认值进行部署时,最好是从新计算一下数据的预期平均长度,调整growth factor,以得到最恰当的设置。内存是珍贵的资源,浪费就太惋惜了。
四、Memcached的检测过时与删除机制
Memcached懒惰检测对象过时机制
首先要知道,Memcached不会主动检测item对象是否过时,而是在进行get操做时检查item对象是否过时以及是否应该删除!
由于不会主动检测item对象是否过时,天然也就不会释放已分配给对象的内存空间了,除非为添加的数据设定过时时间或内存缓存满了,在数据过时后,客户端不能经过key取出它的值,其存储空间将被从新利用。
Memcached使用的这种策略为懒惰检测对象过时策略,即本身不监控存入的key/value对是否过时,而是在获取key值时查看记录的时间戳(sed key flag exptime bytes),从而检查key/value对空间是否过时。这种策略不会在过时检测上浪费CPU资源。
Memcached懒惰删除对象机制
当删除item对象时,通常不会释放内存空间,而是作删除标记,将指针放入slot回收插槽,下次分配的时候直接使用。
Memcached在分配空间时,会优先使用已通过期的key/value对空间;若分配的内存空间占满,Memcached就会使用LRU算法来分配空间,删除最近最少使用的key/value对,从而将其空间分配给新的key/value对。在某些状况下(完整缓存),若是不想使用LRU算法,那么能够经过“-M”参数来启动Memcached,这样,Memcached在内存耗尽时,会返回一个报错信息,以下:
-M rerurn error on memory exhausted(rather than removing items)
下面针对Memcached删除机制进行一个小结
不主动检测item对象是否过时,而是在get时才会检查item对象是否过时以及是否应该删除。
当删除item对象时,通常不释放内存空间,而是作删除标记,将指针放入slot回收插槽,下次分配的时候直接使用。
当内存空间满的时候,将会根据LRU算法把最近最少使用的item对象删除。
数据存入能够设定过时时间,可是数据过时后不会被当即删除,而是在get时检查item对象是否过时以及是否应该删除。
若是不但愿系统使用LRU算法清除数据,能够用使用-M参数。
5、Memcached服务安装
Memcached的安装比较简单,支持Memcached的平台常见的有Linux,FreeBSD,Solaris,Windows。这里以Centos6.5为例进行讲解。
[root@6 yum.repos.d]# pwd /etc/yum.repos.d [root@6 yum.repos.d]# wget http://mirrors.163.com/.help/CentOS6-Base-163.repo
[root@6 yum.repos.d]# ls bak CentOS6-Base-163.repo CentOS-Media.repo [root@6 yum.repos.d]# yum -y clean all [root@6 yum.repos.d]# yum makecache
[root@6 yum.repos.d]# yum -y install libevent libevent-devel nc [root@6 yum.repos.d]# rpm -qa install libevent libevent-devel nc libevent-1.4.13-4.el6.x86_64 libevent-devel-1.4.13-4.el6.x86_64 nc-1.84-24.el6.x86_64
安装Memcached(可用光盘安装)
[root@6 yum.repos.d]# yum -y install memcached
6、Memcached服务的基本管理
一、启动Memcached
[root@6 yum.repos.d]# which memcached /usr/bin/memcached [root@6 yum.repos.d]# memcached -m 16m -p 11211 -d -u root -c 8192 [root@6 yum.repos.d]# ss -antup | grep mem udp UNCONN 0 0 *:11211 *:* users:(("memcached",1632,28)) udp UNCONN 0 0 :::11211 :::* users:(("memcached",1632,29)) tcp LISTEN 0 128 :::11211 :::* users:(("memcached",1632,27)) tcp LISTEN 0 128 *:11211 *:* users:(("memcached",1632,26))
能够起多实例修改-p端口便可
-m指定占用内存的大小,询问开发人员 -p指定端口
-d以守护进程的方式 -u指定用户 -c可并发链接数
修改端口再次启动
[root@6 yum.repos.d]# memcached -m 16m -p 11212 -d -u root -c 8192 [root@6 yum.repos.d]# ss -antup | grep mem
可把上述两个实例的启动命令放入/etc/re.local,以便下次开机能够自启动
二、Memcached启动命令相关参数说明
内存相关设置
命令参数 | 说明 |
---|---|
-m | 指定Memcached服务能够缓存数据的最大内存,默认为64MB |
-M | Memcached服务内存不够时禁止LRU,若是内存满了会报错 |
-n | 为key+value——flags分配的最小内存空间,默认为48字节 |
-f | chunk size增加因子,默认为1.25 |
-L | 启用大内存页,能够下降内存浪费,改进性能 |
并发链接设置
并发链接设置 | 说明 |
---|---|
-c | 最大的并发链接数,默认是1024 |
-t | 线程数,默认4.因为Memcached采用的是NIO,因此太多线程做用不大 |
-R | 每一个event最大请求数,默认是20 |
-C | 禁用CAS(能够禁止版本计数,减小开销) |
测试参数
-v | 打印较少的errors/warnings |
---|---|
-vv | 打印很是多调试信息和错误输出到控制台 |
-vvv | 打印极多的调试信息和错误输出,也打印内部状态转变 |
其余选项可经过“memcached -h”命令来显示。
三、向Memcached中写入数据并检查
向Memcached中添加数据时,注意添加的数据通常为键值对的形式,例如:key1-->values1,key2-->values2
这里把Memcached添加,查询,删除等的命令和MySQL数据库作一个基本类比,见下表:
MySQL数据库管理 | Memcached管理 |
---|---|
MySQL的insert语句 | Memcached的set命令 |
MySQL的select语句 | Memcached的get命令 |
MySQL的delete语句 | Memcached的delete命令 |
(1)经过printf配合nc向Memcached中写入数据
[root@6 ~]# which printf /usr/bin/printf [root@6 ~]# printf "set key1 0 0 5\r\nbenet\r\n" | nc 127.0.0.1 11211 STORED
经过printf配置nc从Memcached中读取数据
[root@6 ~]# printf "get key1\r\n" | nc 127.0.0.1 11211 VALUE key1 0 5 benet END
经过printf配合nc从Memcached中删除数据
[root@6 ~]# printf "delete key1\r\n" | nc 127.0.0.1 11211 DELETED [root@6 ~]# printf "get key1\r\n" | nc 127.0.0.1 11211 END
(2)经过telnet命令写入数据
安装telnet工具
[root@6 ~]# yum -y install telnet [root@6 ~]# which telnet /usr/bin/telnet
经过telnet向Memcached中写入数据
[root@6 ~]# telnet 127.0.0.1 11211
四、操做Memcached相关命令的语法
如下为操做Memcached的相关命令基本语法:
set key1 0 0 6 \r\n benet \r\n <command name><key><flags><exptime><bytes><datablock><string><datablock> STORED <status>
下表为操做Memcached相关命令的详细说明:
五、关闭Memcached
单实例关闭Memcached的方法以下:
[root@6 ~]# ps -ef | grep mem | grep -v grep root 537 2 0 04:19 ? 00:00:00 [vmmemctl] root 1632 1 0 04:45 ? 00:00:00 memcached -m 16m -p 11211 -d -u root -c 8192 root 1670 1 0 04:48 ? 00:00:00 memcached -m 16m -p 11212 -d -u root -c 8192 [root@6 ~]# killall memcached [root@6 ~]# netstat -antup | grep 11211
若启动了多个实例Memcached,使用killall或pkill方式就会同时关闭这些实例!所以最好在启动时增长-P参数指定固定的pid文件,这样便于管理不一样的实例。示例以下:
[root@6 ~]# memcached -m 16m -p 11211 -d -u root -c 8192 -P /var/run/11211.pid [root@6 ~]# memcached -m 16m -p 11212 -d -u root -c 8192 -P /var/run/11212.pid
此时,便可经过kill命令关闭Memcached
[root@6 run]# kill `cat /var/run/11211.pid` [root@6 run]# netstat -antup | grep 11211 [root@6 run]# netstat -antup | grep 11212
六、企业工做场景中如何配置Memcached
在企业实际工做中,通常是开发人员提出需求,说要部署一个Memcached数据缓存。运维人员在接到这个不肯定的需求后,须要和开发人员深刻沟通,进而肯定要将内存指定为多大,或者和开发人员商量如何根据具体业务来指定内存缓存的大小。此外,还要肯定业务的重要性,进而决定是否采起负载均衡,分布式缓存集群等架构,最后肯定要使用多大的并发链接数等。
对于运维人员,部署Memcached通常就是安装Memcached服务器端,把服务启动起来,作好监控,配好开机自启动,基本就OK了,客户端的PHP程序环境通常在安装LNMP环境时都会提早安装Memcached客户端插件,Java程序环境下,开发人员会用第三方的JAR包直接链接Memcached服务。
7、安装Memcached客户端
一、LNMP,PHP环境准备
详细搭建过程略,请同窗们参阅以前的LNMP章节
二、Memcached缓存PHP扩展插件安装
前面已经提过,Memcached分为服务器端软件和客户端插件两部分,这里是Memcached客户端PHP的扩展插件(memcache-2.2.7.tgz)在PHP环境中的安装,用于访问Memcached服务器端数据。
PHP的Memcached扩展插件下载地址为:http://pecl.php.net/package/memcache
[root@LNMP ~]# wget -q http://pecl.php.net/get/memcache-2.2.7.tgz
[root@LNMP ~]# ls anaconda-ks.cfg install.log install.log.syslog memcache-2.2.7.tgz [root@LNMP ~]# tar xf memcache-2.2.7.tgz -C /usr/src/ [root@LNMP ~]# cd /usr/src/memcache-2.2.7/ [root@LNMP memcache-2.2.7]# /usr/local/php/bin/phpize Configuring for: PHP Api Version: 20090626 Zend Module Api No: 20090626 Zend Extension Api No: 220090626 [root@LNMP memcache-2.2.7]# ./configure --enable-memcache --with-php-config=/usr/local/php/bin/php-config [root@LNMP memcache-2.2.7]# make && make install [root@LNMP ~]# ls -l /usr/local/php/lib/php/extensions/no-debug-non-zts-20090626/ total 244
-rwxr-xr-x. 1 root root 246576 Aug 6 12:53 memcache.so #最后生成了memcache.so模块就表示memcache扩展插件成功安装
三、配置Memcache客户端,使其生效
[root@LNMP ~]# cd /usr/local/php/lib/ [root@LNMP lib]# vim php.ini #添加以下两行内容到php.ini文件结尾 extension_dir = "/usr/local/php/lib/php/extensions/no-debug-non-zts-20090626/" extension=memcache.so
四、重启php-fpm服务使PHP的配置修改生效
(1)检查php-fpm语法
[root@LNMP lib]# /usr/local/php/sbin/php-fpm -t [06-Aug-2017 13:03:04] NOTICE: configuration file /usr/local/php5.3.28/etc/php-fpm.conf test is successful
(2)重启fpm
[root@LNMP lib]# pkill php-fpm [root@LNMP lib]# netstat -antup | grep 9000 [root@LNMP lib]# /usr/local/php/sbin/php-fpm [root@LNMP lib]# netstat -antup | grep 9000 tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 46848/php-fpm
3)打开浏览器访问phpinfo页面,若出现以下图所示内容,则表示Memcache客户端安装成功
bbs.yunjisuan.com/test_info.php
五、编写测试Memcached服务的PHP脚本
[root@LNMP bbs]# cat op_mem.php <?php #PHP开始标识 $memcache = new Memcache; #建立一个Memcache对象 $memcache->connect('192.168.0.240','11211') or die ("Could not connect Mc server"); #链接Memcached服务器 $memcache->set('key','yunjisuan book'); #设置一个变量到内存中 $get=$memcache->get('key'); #从内存中取出key echo $get; #输出key值到屏幕 ?> #PHP结束标识 [root@LNMP bbs]# ls index.html op_mem.php test_info.php test_mysql.php
Linux本地测试
[root@LNMP bbs]# /usr/local/php/bin/php op_mem.php #调用php解析器 yunjisuan book #对应的key的值
Windows访问测试
出现上述测试结果,就表示LNMP环境链接Memcached服务成功。
运维人员通常可经过在命令行执行“telnet ip port”的方式登录到Memcached,而后执行一些管理的命令,除了telnet外,nc命令也是一个不错的管理Memcached服务的命令!
有关“telnet ip port”命令前文已经介绍过了,下面将重点讲解经过nc管理及监控Memcached的一些常见操做。
[root@cache01 scripts]# pwd /server/scripts [root@cache01 scripts]# cat mon_mc.sh #!/bin/bash export MemcachedIp=$1 export MemcachedPort=$2 export NcCmd="nc $MemcachedIp $MemcachedPort" export MD5="3fe396c01f03425cb5e2da8186eb090d" USAGE(){ echo "$0 MemcachedIp MemcachedPort" exit 3 } [ $# -ne 2 ] && USAGE printf "set $MD5 0 0 9\r\nyunjisuan\r\n" | $NcCmd >/dev/null 2>&1
if [ $? -eq 0 ];then if [ `printf "get $MD5\r\n"|$NcCmd|grep yunjisuan|wc -l` -eq 1 ];then echo "Memcached status is ok" printf "delete $MD5\r\n"|$NcCmd >/dev/null 2>&1 exit 0
else echo "Memcached status is error" exit 2 fi else echo "Could not connect Mc server" exit 2 fi
Memcached服务正常的状况下,测试检验脚本
[root@cache01 scripts]# sh mon_mc.sh 127.0.0.1 11211 Memcached status is ok
关闭Memcached服务,再测试脚本
[root@cache01 scripts]# kill `cat /var/run/11211.pid` [root@cache01 scripts]# netstat -antup | grep 11211 [root@cache01 scripts]# sh mon_mc.sh 127.0.0.1 11211 Could not connect Mc server
最后开启Memcached服务,测试检验脚本
[root@cache01 scripts]# memcached -m 16m -p 11211 -d -u root -c 8192 -P /var/run/11211.pid [root@cache01 scripts]# netstat -antup | grep 11211 tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN 2053/memcached tcp 0 0 :::11211 :::* LISTEN 2053/memcached udp 0 0 0.0.0.0:11211 0.0.0.0:* 2053/memcached udp 0 0 :::11211 :::* 2053/memcached [root@cache01 scripts]# sh mon_mc.sh 127.0.0.1 11211 Memcached status is ok
[root@cache01 scripts]# printf "stats\r\n"|nc 127.0.0.1 11211 STAT pid 2053 STAT uptime 225 STAT time 1502044003 STAT version 1.4.4 STAT pointer_size 64 STAT rusage_user 0.002999 STAT rusage_system 0.005999 STAT curr_connections 10 STAT total_connections 14 STAT connection_structures 11 STAT cmd_get 1 STAT cmd_set 1 STAT cmd_flush 0 STAT get_hits 1 STAT get_misses 0 STAT delete_misses 0 STAT delete_hits 1 STAT incr_misses 0 STAT incr_hits 0 STAT decr_misses 0 STAT decr_hits 0 STAT cas_misses 0 STAT cas_hits 0 STAT cas_badval 0 STAT auth_cmds 0 STAT auth_errors 0 STAT bytes_read 141 STAT bytes_written 77 STAT limit_maxbytes 16777216 STAT accepting_conns 1 STAT listen_disabled_num 0 STAT threads 4 STAT conn_yields 0 STAT bytes 0 STAT curr_items 0 STAT total_items 1 STAT evictions 0 END
除了上述输出的所有状态之外,Memcached还支持经过如下命令的输入来查看Memcached的部分运行状态信息。目前管理Memcached的命令见下表:
Memcached状态命令 | 说明 |
---|---|
stats | 统计Memcached的各类信息 |
stats settings | 查看一些memcached的设置信息,例如:线程数 |
stats slabs | 查看slabs相关状况,例如:chunksize长度 |
stats items | 查看items相关状况 |
stats sizes | 查看items个数和大小 |
stats reset | 清理统计数据 |
例如,要查看Memcached的统计信息,可先执行“telnet ip 监听端口”命令,登录成功以后执行stats命令,具体过程以下:
[root@LNMP ~]# which telnet /usr/bin/telnet [root@LNMP ~]# telnet 192.168.0.240 11211 Trying 192.168.0.240... Connected to 192.168.0.240. Escape character is '^]'. stats STAT pid 2053 #启动的进程id STAT uptime 682 #到目前1位置启动了多少秒 STAT time 1502044460 STAT version 1.4.4 #Memcached的版本信息 STAT pointer_size 64 STAT rusage_user 0.007998 STAT rusage_system 0.014997 STAT curr_connections 10 #当前的并发链接数 STAT total_connections 15 #总的链接数 STAT connection_structures 11 STAT cmd_get 1 #执行的get命令的次数 STAT cmd_set 1 #执行的set命令的次数 STAT cmd_flush 0 #执行flush命令的次数 STAT get_hits 1 #get的命中数 STAT get_misses 0 #get的非命中数 STAT delete_misses 0 STAT delete_hits 1 STAT incr_misses 0 STAT incr_hits 0 STAT decr_misses 0 STAT decr_hits 0 STAT cas_misses 0 STAT cas_hits 0 STAT cas_badval 0 STAT auth_cmds 0 STAT auth_errors 0 STAT bytes_read 148 STAT bytes_written 848 STAT limit_maxbytes 16777216 #容许使用的最大内存容量 STAT accepting_conns 1 STAT listen_disabled_num 0 STAT threads 4 STAT conn_yields 0 STAT bytes 0 STAT curr_items 0 STAT total_items 1 STAT evictions 0 END
使用printf及nc命令获取状态信息更佳,由于无需交互,可使用如下脚本批量操做
[root@LNMP ~]# printf "stats\r\n"|nc 192.168.0.240 11211 STAT pid 2053 STAT uptime 1270 STAT time 1502045048 STAT version 1.4.4 STAT pointer_size 64 STAT rusage_user 0.011998 STAT rusage_system 0.029995 STAT curr_connections 10 STAT total_connections 24 STAT connection_structures 11 #如下省略若干...
Memcached状态信息的详细说明,同窗们能够经过该表来了解相关信息:
运维人员除了经过命令行管理Memcached之外,还可使用不少的第三方开源管理工具,例如:经过memadmin工具管理及监控Memcached状态,软件的名称为“memadmin-1.0.12.tar.gz”,这个软件的部署十分简单,功能很是强大,可是依赖于PHP环境,推荐同窗们初学Memcached时使用。
由于这个软件是基于PHP程序的,所以,须要有PHP的环境才行,本章已经准备好了LNMP的环境,所以,能够简单地将上述“memadmin-1.0.12.tar.gz”解压到虚拟主机站点目录下,这里仍是以bbs虚拟主机为例进行讲解。
[root@LNMP ~]# ls -l memadmin-1.0.12.tar.gz -rw-r--r--. 1 root root 196734 Aug 6 14:55 memadmin-1.0.12.tar.gz [root@LNMP ~]# tar xf memadmin-1.0.12.tar.gz [root@LNMP ~]# mv memadmin /usr/local/nginx/html/bbs/
[root@LNMP nginx]# cat conf/nginx.conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name www.yunjisuan.com; location / { root html/www; index index.html index.htm; } } server { listen 80; server_name bbs.yunjisuan.com; location / { root html/bbs; index index.html index.htm; } location ~ .*\.(php|php5)$ { root html/bbs; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi.conf; } } }
打开浏览器输入域名:http://bbs.yunjisuan.com/memadmin/index.php
程序的管理页面以下图所示:
提示:
用户名和密码都是admin
下面给你们介绍一个Memcached服务应用优化的企业案例。用户访问网站打开页面很慢,经运维人员排查后,发现MySQL数据库负载很高,load值大概为20~30,以下:
[root@LNMP ~]# uptime 10:41:01 up 15:02, 4 users, load average: 20, 15, 10 #登录数据库后,使用“show full processlist;”查看,或者在Linux命令行使用下面的命令查看: mysql -uroot -p123123 -e "show full processlist"|grep -vi sleep
发现数据库中像“LIKE‘%杜冷丁%’”这样的SQL语句特别多,致使数据库负载很高,咱们都知道像LIKE‘%杜冷丁%’这样的SQL语句对于MySQl数据库来讲,利用索引没有太大的优化余地。
打开该网站首页查看,发现该首页有一个搜索框,根据前面查看的SQL语句形式,能够推测上述“LIKE%杜冷丁%”应该是搜索框的语句带来的结果。过后从这个公司的数据库维护人员处获得了证明,请问若是是你,你该如何优化解决当前的问题呢?
大概的优化方案思路以下:
下图是针对方案6给出的大型网站搜索集群架构逻辑案例图
Memcached服务的额安装配置简单,几乎不须要优化就能够跑的很好,在特殊的大并发高访问量的场合才须要进行一些优化。
例如:每次新增数据到数据库的同时,就将数据写入或者复制一份到Memcached里,而后从业务逻辑上让程序优先读缓存,没有数据再查数据库。
当网站后端的数据库数据量很大时,单台Memcached就没法存放绝大部分的数据库内数据,致使Memcached服务的命中率很低,此时,能够采用一致性哈希分布式缓存集群架构,提高网站的命中率,一致性哈希能够由程序实现或者支持一致性哈希算法的负载均衡器实现。
当访问量增大时,在整个网站集群架构中最早出现瓶颈的几乎都是后端的数据库或用于存储的服务器,在企业生产工做中应尽可能把用户的访问请求往整个网站架构的最前面推,即当用户请求数据时,越是在靠近用户端返回数据,效果就越好。
为了缓解应用对数据库的高并发访问压力,大型网站都会在数据库层配置数据读写分离,并提供读的数据库作负载均衡,逻辑图以下图所示:其中是以Amoeba软件做为读写分离说明的。
因为访问数据库读写的是磁盘,因此,对于高并发的业务场景,上述读写分离的架构仍是远远解决不了问题的,根据离访问用户越近效率越高以及用内存代替磁盘的架构思想,能够在数据库架构的前端部署Memcached服务做为缓存区,最大限度地把对数据库查询信息保存在Memcached服务的内存中,这样前端的应用服务就可以迅速地从Memcached中读取到本来在数据库中才能读取到的数据,从而加快了网站的访问速度。
因为单台Memcached服务器的内存容量是有限的,而且单台也存在单点故障,所以,大型网站每每会将多个memcached服务器组合成集群提供服务,那么怎么组合效率才更高呢?
(1)缓存服务器使用常规负载均衡模式的问题
在常规负载均衡模式中,集群节点上的程序和数据都是同样的,例如Web集群。而缓存集群设计下的全部节点缓存的数据就不能都同样,由于这样一来,访问数据命中率会很是低下,低下的缘由主要有两个:
下图是缓存服务器使用常规负载均衡模式的问题图解
(2)分布式缓存集群的优劣势
- Memcached支持分布式集群,其中的方法之一就是在客户端应用程序上进行改造。例如:能够根据key适当进行有规律的封装。好比以用户为主的网站来讲,每一个用户都有UserID,那么能够按照固定的ID来进行提取和存取,假设以1开头的用户保存在第一台Memcached服务器上,以2开头的用过户的数据保存在第二台Memcached服务器上,那么存取数据时都会按照UserID来进行相应的转换和存取。
- 可是这样也有缺点,就是须要对UserID进行判断,若是业务不一致,或者是其余类型的应用,可能不是那么合适,此时能够根据本身的实际业务来进行考虑,或者去想更合适的方法
- 此外,还能够在应用服务器上经过程序用哈希算法或一致性哈希算法调度Memcached服务器,全部Memcached服务器的地址池能够简单地配在每一个程序的配置文件里。而且可在负载均衡器上使用哈希算法或一致性哈希算法,不过此时须要负载均衡器的支持。
1)每一台Memcached服务器的内容都是不同的。这些Memcached服务器缓存的内容加起来接近整个数据库的数据容量。
2)经过在客户端程序或者Memcached的负载均衡器上用hash算法,让同一数据内容都分配到一个Memcached服务器。
3)普通的hash算法对于节点宕机会带来大量的缓存数据流动(失效),可能会引发雪崩效应。
4)一致性哈希算法(还能够带虚拟节点)可让缓存节点宕机对节点的数据流动(失效)降到最低。
(1)取模计算hash
优势:简单,分散性优秀
缺点:添加/删除服务器时,缓存重组代价巨大,影响命中率
例:将26个字母缓存到了3个节点,此时新增长一个节点,访问命中率将降低23%以下表:
(2)Consistent hash(一致性哈希算法)
- 一致性哈希算法(consistent hash)是一种特殊的hash算法,简单地说,在移除以及添加一个cache节点时,它可以尽量小地改变已存在key的映射关系,让缓存服务器缓存的内容受到的影响最小。
- consistent hash算法原理以下图所示,首先现象一个0~2^32-1次方的数值空间,将这个空间想象成一个首(0)尾(2^32-1)相接的圆环,而后算出不一样Memcached服务器节点的哈希值(0~(2^32-1)之间),将这些值分散到上述的圆环上,接着用一样的方法算出存储不一样数据的键的哈希值并映射到相同的圆环上,最后从数据映射到的位置开始顺时针查找,将键对应的数据保存到查找到的第一个服务器上,以下图所示:
假如咱们要添加node5服务器,以下图所示:
能够看到添加node5服务器后,缓存的数据只影响node2到node5之间的数据范围,即node4的一部分数据,缓存到了node5,其余的缓存服务器没有受到影响,当移除服务器时,原理和添加服务器时同样,再也不赘述。
这就是一致性哈希算法的做用,能够最大限度地减小键的从新分布。该算法的实现方法还能够采用更好的虚拟节点的策略思路,一致性哈希算法能够经过在前端使用程序实现或者经过负载均衡器实现。
如下是PHP Web环境集群的session共享存储设置
#默认php.ini中session的类型和配置路径为: [root@LNMP ~]# awk '/session.save_handler/{print NR,$0}/session.save_path/{print NR,$0}' /usr/local/php/lib/php.ini 1461 session.save_handler = files #修改本行数据 1469 ; session.save_path = "N;/path"
1485 ; session.save_path = "N;MODE;/path"
1490 ;session.save_path = "/tmp" #修改本行数据 1566 ; (see session.save_path above), then garbage collection does *not* #修改为以下配置: [root@LNMP ~]# sed -n '1461p;1490p' /usr/local/php/lib/php.ini session.save_handler = memcache session.save_path = "tcp://192.168.0.240:11211" #重启php-fpm服务 [root@LNMP ~]# pkill php-fpm [root@LNMP ~]# netstat -antup | grep 9000 [root@LNMP ~]# /usr/local/php/sbin/php-fpm [root@LNMP ~]# netstat -antup | grep 9000 tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 1393/php-fpm
说明:
192.168.0.240:11211为Memcached数据库缓存的IP及端口
上述配置适合LNMP/LAMP环境
Memcached服务器也能够是多台,而且可经过hash算法调度
配置完毕经过phpinfo页面查看效果以下图所示:
优势:
1)读写速度上会比普通files速度快不少
2)能够解决多个服务器共用session的难题
缺点:
1)session数据都保存在memory中,持久化方面有所欠缺,但对session数据来讲不是问题。
2)通常是单台,若是部署多台,多台之间没法数据同步。经过hash算法分配依然有session丢失的问题。
对于上面的缺点,解决思路以下:
1)能够用其余的持久化系统存储sessions,例如:redis,ttserver来替代Memcached
2)高性能高并发场景,cookies效率比session要好不少,所以,大网站都会用cookies解决会话共享问题
3)有的已经就业了的同窗经过牺牲LB的负载均衡的策略实现,例如:lvs-p,nginx ip_hash等,但这些不是好的方法。