1、什么是Memcached
1.1、Memcached概述
Memcached是一个免费的开源的、高性能的、具有又分布式内存对象的缓存系统,它通过减轻数据库负载加速动态WEB应用,
1.2、Memcached和数据库交互流程
(1)、检查客户端请求的数据是在Memcached中存在,如果存在,直接把请求的数据返回,不再对数据进行任何操作。
(2)、如果请求的数据不再Memcache中,就去查询数据库,把从数据库中获取的数据返回给客户端,同时把数据缓存一份到Memcahe中
(3)、每次更新数据库(如果更新、删除数据库的数据)的同时更新Memcache中的数据,保证Memcache中的数据数据库中的数据一致。
(4)、当分配的Memcache内存空间用完之后,会使用LRU(Least Recetnly Used 最近最少使用
)策略加到期失效策略,失效的数据首先被替换掉,然后再替换掉最近使用的数据.
1.3、Memcached和数据库交互流程图
2、Memcahed的特征
2.1、Memached特征如下:
Memcached作为高性能的缓存服务器,具有如下特征:
(1)、协议简单
Memcahed的协议实现比较简单,使用的是基于文本的协议,能直接通过telnet在服务器上存取数据.
(2)、基于libevent的处理
Libevent使一套利用C开发的程序库,它将BSD系统kqueue Linux系统的epoll等事件处理功能封装成一个接口,确保即使服务端的链接数增加也能发挥很好的性能.Memcached利用这个库进行异步事件处理。
(3)、内置的内存管理方式
当内存但终得数据空间沾满时,使用LRU算法自动删除不使用的缓存,即重用过期数据的内存空间,Memcahed的为缓存系统设计的.没有考虑数据的容灾问题,和机器的内存一样,重启机器数据将会丢失
(4)、互不通信的Memcached之间有分布特征。
各个Memcahed服务器之间相互不通信,都是独立的存取数据,不共享任何信息,通过对客户端的设计,让Memcahed具有分布式,能支持海量缓存的大规模一个应用.
memcached尽管是“分布式”缓存服务器,但服务器端并没有分布式功能。各个memcached不会互相通信以共享信息。那么,怎样进行分布式呢?这完全取决于客户端的实现。本文也将介绍memcached的分布式。
2.2、Memached原理:
Memcahed 是一种C/S模式,在服务器端启动服务守护进程,此时可以指定监听的IP地址,首先 memcached 是以守护程序方式运行于一个或多个服务器中,随时接受客户端的连接操作,客户端可以由各种语言编写,目前已知的客户端 API 包括 Perl/PHP/Python/Ruby/Java/C#/C 等等。客户端在与 memcached 服务建立连接之后,接下来的事情就是存取对象了,每个被存取的对象都有一个唯一的标识符 key,存取操作均通过这个 key 进行,保存到memcached 中的对象实际上是放置内存中的,并不是保存在 cache 文件中的,这也是为什么 memcached 能够如此高效快速的原因。注意,这些对象并不是持久的,服务停止之后,里边的数据就会丢失。
与许多 cache 工具类似,Memcached 的原理并不复杂。它采用了C/S的模式,在 server 端启动服务进程,在启动时可以指定监听的 ip,自己的端口号,所使用的内存大小等几个关键参数。一旦启动,服务就一直处于可用状态。Memcached 的目前版本是通过C实现,采用了单进程,单线程,异步I/O,基于事件 (event_based) 的服务方式.使用libevent 作为事件通知实现。多个 Server 可以协同工作,但这些 Server 之间是没有任何通讯联系的,每个 Server 只是对自己的数据进行管理。Client 端通过指定 Server 端的 ip 地址(通过域名应该也可以)。需要缓存的对象或数据是以 key->value对的形式保存在Server端。key 的值通过 hash 进行转换,根据 hash 值把 value 传递到对应的具体的某个 Server 上。当需要获取对象数据时,也根据 key 进行。首先对 key 进行 hash,通过获得的值可以确定它被保存在了哪台 Server 上,然后再向该 Server 发出请求。Client 端只需要知道保存 hash(key) 的值在哪台服务器上就可以了。
其实说到底,memcache 的工作就是在专门的机器的内存里维护一张巨大的 hash 表,来存储经常被读写的一些数组与文件,从而极大的提高网站的运行效率。
3、Memcahed的安装
3.1、安装libevnet
Memcache用到了libevent这个库用于Socket的处理,所以还需要安装libevent。(如果你的系统已经安装了libevent,可以不用安装
#wget http://cloud.github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz
# ls /usr/lib | grep libevent
# mkdir /opt/tmp && cd /opt/tmp
# mv /libevent-2.0.21-stable.tar.gz /opt/tmp
# tar -xvf libevent-2.0.21-stable.tar.gz
# cd libevent-2.0.21-stable
# ./configure --prefix=/usr && make && make install
3.2、安装memcached
# wget http://www.danga.com/memcached/dist/memcached-1.4.0.tar.gz
# tar -xvf memcached-1.4.0.tar.gz && cd memcached-1.4.0
# ./configure --with-libevent=/usr && make && make install
# ls -al /usr/local/bin/memcached 检测是否安装成功
3.2、启动memcached
/usr/local/bin/memcached -d -m 10 -u root -l 127.0.0.1 -p 12000 -c 512 -P /tmp/memcached.pid
-d选项是启动一个守护进程,
-m是分配给Memcache使用的内存数量,单位是MB,我这里是10MB,正常来说都分1024或者根据业务来分
-u是运行Memcache的用户,我这里是root,
-l是监听的服务器IP地址,如果有多个地址的话,我这里指定了服务器的IP地址192.168.0.200,
-p是设置Memcache监听的端口,我这里设置了12000,最好是1024以上的端口,
-c选项是最大运行的并发连接数,默认是1024,我这里设置了256,按照你服务器的负载量来设定,
-P是设置保存Memcache的pid文件,我这里是保存在 /tmp/memcached.pid
4、Memcahed测试
4.1、常见出错
这说明没有找到文件:libevent-1.2.so.1解决办法如下:
/usr/local/bin/memcached: error while loading shared libraries: libevent-2.0.so.5: cannot open shared object file: No such file or directory
# ln -s /usr/lib/libevent-2.0.so.5 /usr/lib64/libevent-2.0.so.5
4.2、基本测试
# telete 127.0.0.1 12000
# telnet 127.0.0.1 12000
set test 0 0 3 向test当中存储数据
123 输入的key为test存入数据
STORED 返回set结果
get test 获取数据
VALUE test 0 3
123 取得key为test中的数据
incr test 1 数据 增加1
124
decr test 2 数据减少2
122
quit
4.3、参数说明
>status pid Process id of this server process (memcache服务器的进程ID) uptime Number of seconds this server has been running (服务器已经运行的秒数) time Current UNIX time according to the server (服务器当前的UNIX时间) version Version string of this server (memcache版本) pointer_size Current system pointer 当前操作系统的指针大小(32位系统一般是32bit) rusage_user Accumulated user time for this process (该进程累计的用户时间(秒:微妙)) rusage_system Accumulated system time for this process (该进程累计的系统时间(秒:微妙)) curr_items Current number of items stored by the server (服务器当前存储的内容数量) total_items Total number of items stored by this server ever since it started (服务器启动以来存储过的内容总数) bytes Current number of bytes used by this server to store items (服务器当前存储内容所占用的字节数) curr_connections Number of open connections (当前打开着的连接数量) total_connections Total number of connections opened since the server started running (服务器运行以来接受的连接总数) connection_structures Number of connection structures allocated by the server (服务器分配的连接结构的数量) cmd_get Cumulative number of retrieval requests (get命令(获取)总请求次数) cmd_set Cumulative number of storage requests (set命令(保存)总请求次数) get_hits Number of keys that have been requested and found present (请求成功的总次数) get_misses Number of items that have been requested and not found (请求失败的总次数) threads Current number of thread (当前线程数) bytes_read Total number of bytes read by this server from network (服务器从网络读取到的总字节数) bytes_written Total number of bytes sent by this server to network (服务器向网络发送的总字节数) limit_maxbytes Number of bytes this server is allowed to use for storage. (服务器在存储时被允许使用的字节总数) evictions Number of valid items removed from cache to free memory for new items (为获取空闲内存而删除的items数(分配给memcache的空间用满后需要删除旧的items来得到空间分配给新的items)) 其中,最关注最多的几个参数: uptime:是memcached运行的秒数。 cmd_get:是查询缓存的次数。 cmd_get/uptime 结果是平均每秒请求缓存的次数——结果值越大,说明Memcached的利用率越高,站点的访问量大,如果太低,用文件系统缓存就可以了,根本不会体现出使用memcached的强大性能。 cmd_set:是设置key=>value的次数。整个memcached是个大hash,用cmd_get没有找到的内容,就会调用一下cmd_set写进缓存里。 get_hits:是缓存命中的次数。所谓的命中率 = get_hits/cmd_get * 100%。 get_misses:是缓存未命中的次数。get_misses加上get_hits就等于cmd_get。 stats:显示服务器信息、统计数据等 stats reset:清空统计数据 stats slabs:显示各个slab的信息,包括chunk的大小、数目、使用情况等 stats items:显示各个slab中item的数目和存储时长(最后一次访问距离现在的秒数) quit:退出
4.4、重启
# kill `cat /tmp/memcached.pid`
5、Memcahed分布式部署概念
5.1、方案
通常较小的应用一台Memcached服务器就可以满足需求,但是大中型项目可能就需要多台Memcached服务器了,这就牵涉到一个分布式部署的问题。
对于多台Memcached服务器,怎么确定一个数据应该保存到哪台服务器呢?有两种方案,一是普通Hash分布,二是一致性Hash分布。下面详细说明。
跟DB的Amoeba一样这里通过Hash算法后进行取模 % 2
分布到 server1
server2
<?php /** * 普通Hash分布 */ //Hash函数 function mHash($key){ $md5 = substr(md5($key), 0, 8); $seed = 31; $hash = 0; for($i = 0; $i < 8; $i++){ $hash = $hash * $seed + ord($md5{$i}); $i++; } return $hash & 0x7FFFFFFF; } //假设有2台Memcached服务器 $servers = array( array('host' => '192.168.1.1', 'port' => 11211), array('host' => '192.168.1.1', 'port' => 11211) ); $key = 'MyBlog'; $value = 'http://blog.phpha.com'; $sc = $servers[mHash($key) % 2]; $memcached = new Memcached($sc); $memcached->set($key, $value); ?>