* 什么是缓存和相关的技术?
缓存(cache),通常是指物理存储介质上的一块临时的存储区域,它用于存放那些访问频繁的数据,从而得以提供了对频繁使用数据的快速访问。这有点类似反过来的长尾理论,越是频繁被访问的数据,越是给其以优待(更快地访问速度)(或者,这种过程也叫做“马太效应“)
缓存技术,简单地说,就是使用缓存来存放那些被频繁访问的数据,以提供更快的读取性能。比如CPU会有L1和L2缓存;最近几年的硬盘的缓存则是越做越大,就是为了更好的IO(读取和写入)性能;同样地,在web应用(web app,下同)中,使用缓存技术能够显著地减少常用数据的读取时间。
* memcached
** 什么是memcached?
采用C/S结构、分布式、基于*内存*的对象缓存系统。在使用得当的情况下会有很好的数据读取性能。memcached的主要目的是:第一、显著减少由数据库驱动的应用程序(比如web程序)对数据库的读请求的次数;第二、只计算一次那些很消耗计算资源的结果,以后则通过缓存里的有效备份来快速获取(在RAM存储器的单位存储价格比大白菜贵不了多少的今天,“以存代算”思想的成本更低廉,优势更明显)。
*注意*:建议使用*nix平台。
*注意*:memcached不会考虑访问的认证和安全问题,所以一定要做好防火墙或者用iptable等访问限制的设置(这一点很符合UNIX的哲学之一:只做一件事情并且做好这件事情)。
** 什么场合适合使用memcached?
通常,一个由数据库驱动的且读操作密集型的web应用诞生之时,通常访问数很小,此时数据库本身还能够比较好地提供服务。而在日后当web应用的访问用户数增加时,它就需要频繁地从数据库读取数据(甚至还需要每次耗费很多计算资源进行计算)以得到需要的结果。这个时侯还仅仅依靠数据库(比如MySQL)自身的缓存的话,数据访问就会成为整个web app的瓶颈。为了减轻数据库服务器的负担、提供更小的效应时间和更好的服务质量,memcached等缓存程序和技术就可以派上用场了。比如,可以使用memcached来缓存第一次计算的结果,这样后续使用相同数据时就省却了复杂的计算;退一步说,即便只是简单地缓存数据库中被经常用到的列数据,memcached相比于MySQL等属于数据库自身的缓存功能也有优势:MySQL等由于受到服务器和操作系统体系结构限制,在32位的机器上最多只能使用4GB的虚拟地址空间(也就意味着即使有多于4GB的物理内存,能够有效被单独的一个MySQL进程使用的物理内存也最多是4GB;而且在同一个数据库上通常只能启动一个MySQL实例);MySQL的第二个不足是数据库表里的数据变更会导致整张表的缓存失效,等于需要重建整个缓存,估计没有人喜欢这样的情况。
而memcached的好处在于,只要有多余内存的地方,就可以运行。并且memcached不要求每一个它的进程都被分配同样多的内存,而且对cpu资源的要求也不高。
** 工作原理
memcached所缓存的数据采用”键/值(key/value)”的方式存储。每一个唯一的键标识一段数据。它使用在多台机器上运行的多个memcached进程共同组成一个统一的分布式散列表(hash table)来存储数据。在散列表的空间已经被完全使用的情况下,新插入的数据会使得那些最近不常用的数据被覆盖(采用LRU算法)。
当web应用需要一段特定的数据时,其工作流程如下:首先需要尝试去memcached里取这段数据,如果这段数据正好有效地存在于memcached中(这叫做缓存命中),则直接得到该段数据;否则需要重新计算,把结果存到memcached里,然后再使用该结果(这种情况就是常说的缓存缺失情况之一)。
在开发web应用时,程序员不需要关心数据的具体存储方式和服务器的分布方式(实际上分布式功能是由各种编程语言的客户端实现的)。结合使用良好定义的且简单易用的编程接口和memcache pool,则不需要关心数据的散列存储和读取过程,极大地减轻了程序员的任务,得以能够更专注于业务逻辑。
需要注意的是,键最大被允许的内存长度是250个字节(Bytes),值可以使用的最大内存长度是1兆(MB)。
** 使用memcached有什么好处?
OK,上面废话了一通,下面讲讲实际好处:
- 由于采用了libevent,使得memcached服务器进程的自动扩展非
常容易
- 通过使用Memcache Pool,自动为程序员管理memcached的集群
- 简单易用的编程接口;大部分主流语言(PHP/Python/Ruby)都有
相应的客户端编程库
- 采用自主的内存分配方法,最大程度地减少内存碎片
- 减少数据库服务器为了实现ACID所带来的overhead
** 如何获取和安装
从
http://www.danga.com/memcached/download.bml
下载源代码进行编译安装(需要安装其所依赖的libevent);或者也可以根据特定版本的操作系统,安装对应的二进制版本。
安装完毕以后,通过如下简单的命令行参数即可运行:
memcached -d -m 2048 -l 192.168.1.101 -p 11211
其中的-d表示以守护模式运行本进程,-m表示分配的内存数(以兆字节(MB)为单位),-l表示memcached监听的网络接口的ip地址,-p表示监听的端口。可以在多个有空闲内存的服务器上运行多个memcached的进程(如果在同一台机器上有多个memcached进程,则需要使用不同的端口号,也即对于同一台机器上不同memcached进程,-p后的数字(也即端口号)需要设置为不同的数字)。
OK!接下来我们看看具体在编程语言中如何使用memcached的客户端编程接口。
** 如何使用API
在这一小节中,以PHP语言为例,讲解通常使用memcached缓存的流程。更高阶的使用方法和更多的API请参看”进阶阅读”小节所列的文档。
$memcache = new Memcache();
/*
* 把运行在ip地址为`192.168.1.101`机器上并且在11211端口监听的memcached
* 进程加到memcache pool中
*/
$memcache->addServer(”192.168.1.101″, 11211);
$memcache->addServer(”192.168.1.102″, 11211); // 类似上一行
$memcache->addServer(”192.168.1.103″, 11211);
// 可以添加更多的memcached进程
if( ($foo = $memcache->get(’key’)) === False ) {
$tmp = new stdClass;
$tmp->abc = ‘bar’;
$tmp->baz = ‘xyz’;
$foo = $tmp;
$memcache->set(’key’, $tmp, 0, 300);
}
// 对$foo进行后续的处理
?>
** 缺点
当然了,从某些特定角度和立场来讲memcached也有一些不足(或者,我们可以称之为特性,正如It’s not a bug. It’s a feature!这句话所说的):
- 不能转储
- 不能按照”键(key)”进行遍历
- 非永久存储。掉电以后数据不再。
- 非冗余,不能作为数据库的一个冗余备份。
- 不支持会话(session)。不过在客户端编程库中可以扩展实现
- 没有安全机制和访问授权认证
- 没有容错。不过一台运行memcached的服务器坏了以后只要把这
台机器替换掉即可。
** 进阶阅读
- memcached的官方 wiki:
http://code.google.com/p/memcached/wiki/Clients ,
其中包含各种编程语言的客户端程序库
- PHP memcached的文档:
http://www.php.net/manual/en/book.memcache.php
* 内容预告
关于memcached我们还会继续提供相关的使用研究报告,敬请关注!在下期内容中,将讲述如何更好地使用客户端编程库。
* 声明
本文只是对memcached入门的简单介绍,更由于本人才疏学浅,难免挂一漏万,因此欢迎各位朋友一起交流。请不要吝惜在评论中给出您的宝贵意见。
* 参考文献
[1] memcached: http://www.danga.com/memcached/
[2] wikipedia: http://en.wikipedia.org/wiki/Cache
[3] http://www.slideshare.net/acme/scaling-with-memcached
[4] http://www.slideshare.net/benramsey/give-your-site-a-boost-with-memcache-527212
[5] libevent: http://www.monkey.org/~provos/libevent/