memcache是一个高性能的分布式的内存对象缓存系统,经过在内存里维护一个统一的巨大的hash表,它可以用来存储各类格式的数据,包括图像、视 频、文件以及数据库检索的结果等。Memcache是danga.com的一个项目,最先是为 LiveJournal 服务的,最初为了加速 LiveJournal 访问速度而开发的,后来被不少大型的网站采用。目前全世界很多人使用这个缓存项目来构建本身大负载的网站,来分担数据库的压力。起初做者编写它多是为了 提升动态网页应用,为了减轻数据库检索的压力,来作的这个缓存系统。它的缓存是一种分布式的,也就是能够容许不一样主机上的多个用户同时访问这个缓存系统, 这种方法不只解决了共享内存只能是单机的弊端,同时也解决了数据库检索的压力,最大的优势是提升了访问获取数据的速度!基于memcache和对分布式 cache的理解和解决方案。 memcache彻底能够用到其余地方 好比分布式数据库, 分布式计算等领域。php
Memcache客户端包含两组接口,一组是面向过程的接口,一组是面向对象的接口,具体能够参考PHP手册 “LXXV. Memcache Functions” 这章。
Memcache面向对象的经常使用接口包括:
Memcache::connect -- 打开一个到Memcache的链接
Memcache::pconnect -- 打开一个到Memcache的长链接
Memcache::close -- 关闭一个Memcache的链接
Memcache::set -- 保存数据到Memcache服务器上
Memcache::get -- 提取一个保存在Memcache服务器上的数据
Memcache::replace -- 替换一个已经存在Memcache服务器上的项目(功能相似Memcache::set)
Memcache::delete -- 从Memcache服务器上删除一个保存的项目
Memcache::flush -- 刷新全部Memcache服务器上保存的项目(相似于删除全部的保存的项目)
Memcache::getStats -- 获取当前Memcache服务器运行的状态前端
使用Memcache的网站通常流量都是比较大的,为了缓解数据库的压力,让Memcache做为一个缓存区域,把部分信息保存在内存中,在前端可以迅 速的进行存取。那么通常的焦点就是集中在如何分担数据库压力和进行分布式,毕竟单台Memcache的内存容量的有限的。我这里简单提出个人我的见解,未 经实践,权当参考。
[ 分布式应用]
Memcache原本支持分布式,咱们客户端稍加改造,更好的支持。咱们的key能够适当进行 有规律的封装,好比以user为主的网站来讲,每一个用户都有User ID,那么能够按照固定的ID来进行提取和存取,好比1开头的用户保存在第一台Memcache服务器上,以2开头的用户的数据保存在第二胎 Mecache服务器上,存取数据都先按照User ID来进行相应的转换和存取。
可是这个有缺点,就是须要对User ID进行判断,若是业务不一致,或者其余类型的应用,可能不是那么合适,那么能够根据本身的实际业务来进行考虑,或者去想更合适的方法。
[ 减小数据库压力]
这个算是比较重要的,全部的数据基本上都是保存在数据库当中的,每次频繁的存取数据库,致使数 据库性能极具降低,没法同时服务更多的用户,好比MySQL,特别频繁的锁表,那么让Memcache来分担数据库的压力。咱们须要一种改动比较小,并 且可以不会大规模改变前端的方式来进行改变目前的架构。sql
Memcache的安全
咱们上面的Memcache服务器端都是直接经过客户端链接后直接操做,没有任何的验证过程,这样若是服务器是直接暴露在互联网上的话是比较危险,轻则数 据泄露被其余无关人员查看,重则服务器被***,由于Mecache是以root权限运行的,何况里面可能存在一些咱们未知的bug或者是缓冲区溢出的情 况,这些都是咱们未知的,因此危险性是能够预见的。为了安全起见,我作两点建议,可以稍微的防止***的***或者数据的泄露。数据库
内网访问
最好把两台服务器之间的访问是内网形态的,通常是Web服务器跟Memcache服务器之间。广泛的服务器都是有两块网卡,一块指向互联网,一块指向内 网,那么就让Web服务器经过内网的网卡来访问Memcache服务器,咱们Memcache的服务器上启动的时候就监听内网的IP地址和端口,内网间的 访问可以有效阻止其余非法的访问。
# memcached -d -m 1024 -u root -l 192.168.0.200 -p 11211 -c 1024 -P /tmp/memcached.pid
Memcache服务器端设置监听经过内网的192.168.0.200的ip的11211端口,占用1024MB内存,而且容许最大1024个并发链接缓存
设置防火墙
防火墙是简单有效的方式,若是倒是两台服务器都是挂在网的,而且须要经过外网IP来访问Memcache的话,那么能够考虑使用防火墙或者代理程序来过滤非法访问。
通常咱们在Linux下可使用iptables或者FreeBSD下的ipfw来指定一些规则防止一些非法的访问,好比咱们能够设置只容许咱们的Web服务器来访问咱们Memcache服务器,同时阻止其余的访问。
# iptables -F
# iptables -P INPUT DROP
# iptables -A INPUT -p tcp -s 192.168.0.2 –dport 11211 -j ACCEPT
# iptables -A INPUT -p udp -s 192.168.0.2 –dport 11211 -j ACCEPT
上面的iptables规则就是只容许192.168.0.2这台Web服务器对Memcache服务器的访问,可以有效的阻止一些非法访问,相应的也能够增长一些其余的规则来增强安全性,这个能够根据本身的须要来作安全
有两种方法可使 PHP 做为 memcached 客户端,调用 memcached 的服务进行对象存取操做。服务器
第一种,PHP 有一个叫作 memcache 的扩展,Linux 下编译时须要带上 –enable-memcache[=DIR] 选项,Window 下则在 php.ini 中去掉 php_memcache.dll 前边的注释符,使其可用。架构
除此以外,还有一种方法,能够避开扩展、从新编译所带来的麻烦,那就是直接使用 php-memcached-client。
建议使用第一种办法,虽然有增长php扩展 从新编译php的麻烦。 但一劳永逸,程序不用再包含一个文件,执行时候不用在经过解析器解析代码。 效率比第二种高不少。
程序应用中须要注意
如今状况是db层和web层之间有一桥梁 memcache程序之间。 但不能由于这而彻底中断db 和web之间的联系。 Web 和db之间 要有一个曲线。 即没法使用memecache的时候两者相互通讯。
实现很简单:
例如:
$sql="SELECT count(tid) as num FROM pw_blog b WHERE $where";
if(!$memcache->get(md5($sql))){
$count = $db->get_one($sql);
$sum=$count['num'];
$memcache->set(md5($sql), $sum, false, 300000);
}else{
$sum=$memcache->get(md5($sql));
}
而不要写成:
$sql="SELECT count(tid) as num FROM pw_blog b WHERE $where";
if(!$memcache->get(md5($sql))){
$count = $db->get_one($sql);
$sum=$count['num'];
$memcache->set(md5($sql), $sum, false, 300000);
}
$sum=$memcache->get(md5($sql));
这样的形式,这样 db和web就无路可通了。
关于memcache的内存使用memcached默认状况下采用了名为Slab Allocator的机制分配、管理内存。
Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,以彻底解决内存碎片问题。
Slab Allocation的原理至关简单。 将分配的内存分割成各类尺寸的块(chunk),并把尺寸相同的块分红组(chunk的集合).
memcached根据收到的数据的大小,选择最适合数据大小的slab。 memcached中保存着slab内空闲chunk的列表,根据该列表选择chunk,而后将数据缓存于其中。
memcached不会释放已分配的内存。记录超时后,客户端就没法再看见该记录(invisible,透明),其存储空间便可重复使用
memcached内部不会监视记录是否过时,而是在get时查看记录的时间戳,检查记录是否过时。这种技术被称为lazy(惰性)expiration。所以,memcached不会在过时监视上耗费CPU时间
memcached会优先使用已超时的记录的空间,但即便如此,也会发生追加新记录时空间不足的状况,此时就要使用名为 Least Recently Used(LRU)机制来分配空间。顾名思义,这是删除“最近最少使用”的记录的机制。所以,当memcached的内存空间不足时(没法从slab class 获取到新的空间时),就从最近未被使用的记录中搜索,并将其空间分配给新的记录。从缓存的实用角度来看,该模型十分理想。
此处还有一个参数: M ,不是m
启动时候参数 -m 用来申请内存空间 -M 倒是禁止LRU的。
-M 参数使用在内存用慢的时候会返回错误。 原本咱们不是把memcached用作存储,而是用作缓存,因此推荐使用LRU。