这篇FAQ包含了你们广泛关心的问题。很是值得一看。php
原文:http://blog.csdn.net/jarfield/archive/2009/07/05/4322953.aspxhtml
最后更新时间 2009-04-10 更新人 dormando@rydia.net
这里收集了常常被问到的关于memcached的问题java
通常的问题
什么是memcached?
memcached是一个高性能的、分布式的、内存对象缓存系统。memcached本质上是一个通用的缓存系统,可是它一般被用来减少数据库的负载,以达到加速dynamic web应用的目的。mysql
Dange Interactive (开发memcached的组织机构,译者注)开发memcached的目的是,加快LiveJournal.com 的速度。LiveJournal.com 这个网站拥有大量的web server和database server,天天访问的用户数高达1百万,天天的动态网页PV高达2千万+。有了memcached,数据库就跟没事同样,其负载被大大减少。Memcached加快了动态网页的响应时间,提升了资源利用率,加快了memcached不命中时数据库的访问速度。
从哪得到memcached?
到这个下载页面 下载吧!
怎么安装memcached?
能够参考安装指南 ,也可使用操做系统的软件包管理系统来自动下载安装(apt, yum等)。
若是您的linux发行版没有memcached,或者有了memcached但版本不够新,您还能够从源代码安装。从咱们的下载页面得到源代码的tar包,而后在shell中执行如下命令:
$ tar -zxvf memcached-1.x.x.tar.gz
$ ./configure --enable-threads (若是您想使用多线程工做方式)
$ make
$ make test
$ sudo make install
您可使用'./configure --help' 能够查看全部的选项。
哪些平台能够运行memcached?
任何有空闲内存的地方均可以!Memcached能够运行在linux、BSD、windows。它只须要不多的CPU时间,因此不管哪里有空闲内存,哪里就能够运行它。
什么状况下适合使用memcached?
若是您的网站包含了访问量很大的动态网页,于是数据库负载很高,并且大部分数据库请求都是读操做,那么memcached能够帮您显著地减少数据库负载。linux
Memcached一样适用在其余不少场合。至于到底适用哪些场合,您能够通读Memcached FAQ和相关的指南来得到一些灵感。若是您的数据库负载比较低但CPU使用率很高,您能够缓存计算好的结果( computed objects )和渲染后的模板(enderred templates)。经过memcached,您能够缓存session数据、临时数据以减小对他们的数据库写操做,缓存一些很小可是被频繁访问的文件, 缓存Web 'services'(非IBM宣扬的Web Services,译者注)或RSS feeds的结果...
即便您的资源(CPU、内存、数据库等,译者注)很充足,memcached至少也能够帮您加快页面的渲染速度。
什么状况下不适合适用memcached?
参见这里 。(下面也翻译这个页面)
Memcached的确很棒!但也不是每种场合都适用...web
通常来讲,您的应用可使用memcached的客户端库来访问一个或多个memcached。sql
这个客户端页面上列出了全部可用的API库,包括Perl, C, C#, PHP, Python, Java, Ruby, PostgreSQL的存储过程及触发器。shell
您能够根据memcached协议 编写本身的客户端库。数据库
若是您想把memcached用做数据存储媒介而不是缓存,那么您应该使用database。MySQL Cluster拥有一些与memcached相似的特性(尽管MySQL Cluster安装并不容易),并且MySQL Cluster彻底能够胜任一个可靠的分布存储媒介。
不!Memcached不支持也不计划支持这个操做。这个操做的速度相对缓慢且阻塞其余的操做(这里的缓慢时相比memcached其余的命令)。如前面所说,memcached是一个缓存,不是数据库。Tugela 和 memcachedb 是memcached派生出的系统,它们速度比较慢,可是行为更有点像数据库。
固然,memcached毕竟是软件,因此从某种角度说,答案最终确定是YES。可是这个操做确实慢并且阻塞memcached。对于开发和测试服务器来讲,这不是问题,可是对于99.9%的真正部署来讲,答案是NO。
咱们前面提到的“阻塞memcached”到底是什么意思呢?memcached全部非调试(non-debug)命令,例如add, set, get, fulsh这些命令,不管memcached中存储了多少数据,它们的执行都只消耗常量时间。任何遍历全部item的命令执行所消耗的时间,将随着memcached中数据量的增长而增长。当其余命令由于等待(遍历全部item的命令执行完毕)而不能获得执行,阻塞就发生了。
也许您能够说,“删除我全部的key”这个命令平均只花费半秒钟,我有足够的CPU空闲时间,我隔几秒钟才执行一次这个命令,那么还有什么问题吗(还不能遍历全部的item吗)?(固然有问题)由于这半秒钟,其余的请求都至少延迟半秒钟。It'll take as long as it takes the hardware to process through that queue in order to catch up. So all of your other requests end up taking too long.
因此咱们努力不作这样的事情。若是您确实须要遍历全部的item,考虑使用MySQL吧,使用主键访问数据,您还可使用一个辅助索引加快搜索速度。
最后更新时间 2009-04-10 更新人 dormando@rydia.net
这里收集了常常被问到的关于memcached的问题
Memcached的神奇来自两阶段哈希(two-stage hash)。Memcached就像一个巨大的、存储了不少<key,value>对的哈希表。经过key,能够存储或查询任意的数据。
客户端能够把数据存储在多台memcached上。当查询数据时,客户端首先参考节点列表计算出key的哈希值(阶段一哈希),进而选中一个节点;客户端将请求发送给选中的节点,而后memcached节点经过一个内部的哈希算法(阶段二哈希),查找真正的数据(item)。
举个列子,假设有3个客户端1, 2, 3,3台memcached A, B, C:
Client 1想把数据"barbaz"以key "foo"存储。Client 1首先参考节点列表(A, B, C),计算key "foo"的哈希值,假设memcached B被选中。接着,Client 1直接connect到memcached B,经过key "foo"把数据"barbaz"存储进去。Client 2使用与Client 1相同的客户端库(意味着阶段一的哈希算法相同),也拥有一样的memcached列表(A, B, C)。
因而,通过相同的哈希计算(阶段一),Client 2计算出key "foo"在memcached B上,而后它直接请求memcached B,获得数据"barbaz"。
各类客户端在memcached中数据的存储形式是不一样的(perl Storable, php serialize, java hibernate, JSON等)。一些客户端实现的哈希算法也不同。可是,memcached服务器端的行为老是一致的。
最后,从实现的角度看,memcached是一个非阻塞的、基于事件的服务器程序。这种架构能够很好地解决C10K problem ,并具备极佳的可扩展性。
能够参考A Story of Caching ,这篇文章简单解释了客户端与memcached是如何交互的。
请仔细阅读上面的问题(即memcached是如何工做的)。Memcached最大的好处就是它带来了极佳的水平可扩展性,特别是在一个巨大的系统中。因为客户端本身作了一次哈希,那么咱们很容易增长大量memcached到集群中。memcached之间没有相互通讯,所以不会增长 memcached的负载;没有多播协议,不会网络通讯量爆炸(implode)。memcached的集群很好用。内存不够了?增长几台 memcached吧;CPU不够用了?再增长几台吧;有多余的内存?在增长几台吧,不要浪费了。
基于memcached的基本原则,能够至关轻松地构建出不一样类型的缓存架构。除了这篇FAQ,在其余地方很容易找到详细资料的。
看看下面的几个问题吧,它们在memcached、服务器的local cache和MySQL的query cache之间作了比较。这几个问题会让您有更全面的认识。
memcached和MySQL的query cache相比,有什么优缺点?
把memcached引入应用中,仍是须要很多工做量的。MySQL有个使用方便的query cache,能够自动地缓存SQL查询的结果,被缓存的SQL查询能够被反复地快速执行。Memcached与之相比,怎么样呢?MySQL的query cache是集中式的,链接到该query cache的MySQL服务器都会受益。
memcached和服务器的local cache(好比PHP的APC、mmap文件等)相比,有什么优缺点?
首先,local cache有许多与上面(query cache)相同的问题。local cache可以利用的内存容量受到(单台)服务器空闲内存空间的限制。不过,local cache有一点比memcached和query cache都要好,那就是它不但能够存储任意的数据,并且没有网络存取的延迟。
Memcached主要的cache机制是LRU(最近最少用)算法+超时失效。当您存数据到memcached中,能够指定该数据在缓存中能够呆多久Which is forever, or some time in the future。若是memcached的内存不够用了,过时的slabs会优先被替换,接着就轮到最老的未被使用的slabs。
memcached如何实现冗余机制?
不实现!咱们对这个问题感到很惊讶。Memcached应该是应用的缓存层。它的设计自己就不带有任何冗余机制。若是一个memcached节点失去了全部数据,您应该能够从数据源(好比数据库)再次获取到数据。您应该特别注意,您的应用应该能够容忍节点的失效。不要写一些糟糕的查询代码,寄但愿于memcached来保证一切!若是您担忧节点失效会大大加剧数据库的负担,那么您能够采起一些办法。好比您能够增长更多的节点(来减小丢失一个节点的影响),热备节点(在其余节点down了的时候接管IP),等等。
memcached如何处理容错的?
不处理!:) 在memcached节点失效的状况下,集群没有必要作任何容错处理。若是发生了节点失效,应对的措施彻底取决于用户。节点失效时,下面列出几种方案供您选择:
您不该该这样作!Memcached是一个非阻塞的服务器。任何可能致使memcached暂停或瞬时拒绝服务的操做都应该值得深思熟虑。向memcached中批量导入数据每每不是您真正想要的!想象看,若是缓存数据在导出导入之间发生了变化,您就须要处理脏数据了;若是缓存数据在导出导入之间过时了,您又怎么处理这些数据呢?
所以,批量导出导入数据并不像您想象中的那么有用。不过在一个场景却是颇有用。若是您有大量的从不变化 的数据,而且但愿缓存很快热(warm)起来,批量导入缓存数据是颇有帮助的。虽然这个场景并不典型,但却常常发生,所以咱们会考虑在未来实现批量导出导入的功能。
Steven Grimm,一如既往地,,在邮件列表中给出了另外一个很好的例子:http://lists.danga.com/pipermail/memcached/2007-July/004802.html 。
可是我确实须要把memcached中的item批量导出导入,怎么办??
好吧好吧。若是您须要批量导出导入,最可能的缘由通常是从新生成缓存数据须要消耗很长的时间,或者数据库坏了让您饱受痛苦。
若是一个memcached节点down了让您很痛苦,那么您还会陷入其余不少麻烦。您的系统太脆弱了。您须要作一些优化工做。好比处理"惊群"问题(好比 memcached节点都失效了,反复的查询让您的数据库不堪重负...这个问题在FAQ的其余提到过),或者优化很差的查询。记住,Memcached 并非您逃避优化查询的借口。
若是您的麻烦仅仅是从新生成缓存数据须要消耗很长时间(15秒到超过5分钟),您能够考虑从新使用数据库。这里给出一些提示:
上面的方法均可以引入memcached,在重启memcached的时候仍然提供很好的性能。因为您不须要小心"hot"的item被 memcached LRU算法忽然淘汰,用户不再用花几分钟来等待从新生成缓存数据(当缓存数据忽然从内存中消失时),所以上面的方法能够全面提升性能。
关于这些方法的细节,详见博客:http://dormando.livejournal.com/495593.html 。
memcached是如何作身份验证的?
没有身份认证机制!memcached是运行在应用下层的软件(身份验证应该是应用上层的职责)。memcached的客户端和服务器端之因此是轻量级的,部分缘由就是彻底没有实现身份验证机制。这样,memcached能够很快地建立新链接,服务器端也无需任何配置。
若是您但愿限制访问,您可使用防火墙,或者让memcached监听unix domain socket。
memcached的多线程是什么?如何使用它们?
线程就是定律(threads rule)!在Steven Grimm和Facebook的努力下,memcached 1.2及更高版本拥有了多线程模式。多线程模式容许memcached可以充分利用多个CPU,并在CPU之间共享全部的缓存数据。memcached使用一种简单的锁机制来保证数据更新操做的互斥。相比在同一个物理机器上运行多个memcached实例,这种方式可以更有效地处理multi gets。
若是您的系统负载并不重,也许您不须要启用多线程工做模式。若是您在运行一个拥有大规模硬件的、庞大的网站,您将会看到多线程的好处。
更多信息请参见:http://code.sixapart.com/svn/memcached/trunk/server/doc/threads.txt 。
简单地总结一下:命令解析(memcached在这里花了大部分时间)能够运行在多线程模式下。memcached内部对数据的操做是基于不少全局锁的(所以这部分工做不是多线程的)。将来对多线程模式的改进,将移除大量的全局锁,提升memcached在负载极高的场景下的性能。
memcached能接受的key的最大长度是多少?
key的最大长度是250个字符。须要注意的是,250是memcached服务器端内部的限制,若是您使用的客户端支持"key的前缀"或相似特性,那么key(前缀+原始key)的最大长度是能够超过250个字符的。咱们推荐使用使用较短的key,由于能够节省内存和带宽。
memcached对item的过时时间有什么限制?
过时时间最大能够达到30天。memcached把传入的过时时间(时间段)解释成时间点后,一旦到了这个时间点,memcached就把item置为失效状态。这是一个简单但obscure的机制。
memcached最大能存储多大的单个item?
1MB。若是你的数据大于1MB,能够考虑在客户端压缩或拆分到多个key中。
为何单个item的大小被限制在1M byte以内?
啊...这是一个你们常常问的问题!
简单的回答:由于内存分配器的算法就是这样的。
详细的回答:Memcached的内存存储引擎(引擎未来可插拔...),使用slabs来管理内存。内存被分红大小不等的slabs chunks(先分红大小相等的slabs,而后每一个slab被分红大小相等chunks,不一样slab的chunk大小是不相等的)。chunk的大小依次从一个最小数开始,按某个因子增加,直到达到最大的可能值。
若是最小值为400B,最大值是1MB,因子是1.20,各个slab的chunk的大小依次是:slab1 - 400B slab2 - 480B slab3 - 576B ...
slab中chunk越大,它和前面的slab之间的间隙就越大。所以,最大值越大,内存利用率越低。Memcached必须为每一个slab预先分配内存,所以若是设置了较小的因子和较大的最大值,会须要更多的内存。
还有其余缘由使得您不要这样向memcached中存取很大的数据...不要尝试把巨大的网页放到mencached中。把这样大的数据结构load和unpack到内存中须要花费很长的时间,从而致使您的网站性能反而很差。
若是您确实须要存储大于1MB的数据,你能够修改slabs.c:POWER_BLOCK的值,而后从新编译memcached;或者使用低效的malloc/free。其余的建议包括数据库、MogileFS等。
我能够在不一样的memcached节点上使用大小不等的缓存空间吗?这么作以后,memcached可以更有效地使用内存吗?
Memcache客户端仅根据哈希算法来决定将某个key存储在哪一个节点上,而不考虑节点的内存大小。所以,您能够在不一样的节点上使用大小不等的缓存。可是通常都是这样作的:拥有较多内存的节点上能够运行多个memcached实例,每一个实例使用的内存跟其余节点上的实例相同。
什么是二进制协议,我该关注吗?
关于二进制最好的信息固然是二进制协议规范:http://code.google.com/p/memcached/wiki/MemcacheBinaryProtocol 。
二进制协议尝试为端提供一个更有效的、可靠的协议,减小客户端/服务器端因处理协议而产生的CPU时间。
根据Facebook的测试,解析ASCII协议是memcached中消耗CPU时间最多的环节。因此,咱们为何不改进ASCII协议呢?
在这个邮件列表的thread中能够找到一些旧的信息:http://lists.danga.com/pipermail/memcached/2007-July/004636.html 。
memcached的内存分配器是如何工做的?为何不适用malloc/free!?为什么要使用slabs?
实际上,这是一个编译时选项。默认会使用内部的slab分配器。您确实确实应该使用内建的slab分配器。最先的时候,memcached只使用malloc/free来管理内存。然而,这种方式不能与OS的内存管理之前很好地工做。反复地malloc/free形成了内存碎片,OS最终花费大量的时间去查找连续的内存块来知足malloc的请求,而不是运行memcached进程。若是您不一样意,固然可使用malloc!只是不要在邮件列表中抱怨啊:)
slab分配器就是为了解决这个问题而生的。内存被分配并划分红chunks,一直被重复使用。由于内存被划分红大小不等的slabs,若是item的大小与被选择存放它的slab不是很合适的话,就会浪费一些内存。Steven Grimm正在这方面已经作出了有效的改进。
邮件列表中有一些关于slab的改进(power of n 仍是 power of 2)和权衡方案:http://lists.danga.com/pipermail/memcached/2006-May/002163.htmlhttp://lists.danga.com/pipermail/memcached/2007-March/003753.html 。
若是您想使用malloc/free,看看它们工做地怎么样,您能够在构建过程当中定义USE_SYSTEM_MALLOC。这个特性没有通过很好的测试,因此太不可能获得开发者的支持。
更多信息:http://code.sixapart.com/svn/memcached/trunk/server/doc/memory_management.txt 。
memcached是原子的吗?
固然!好吧,让咱们来明确一下:
全部的被发送到memcached的单个命令是彻底原子的。若是您针对同一份数据同时发送了一个set命令和一个get命令,它们不会影响对方。它们将被串行化、前后执行。即便在多线程模式,全部的命令都是原子的,除非程序有bug:)
命令序列不是原子的。若是您经过get命令获取了一个item,修改了它,而后想把它set回memcached,咱们不保证这个item没有被其余进程(process,未必是操做系统中的进程)操做过。在并发的状况下,您也可能覆写了一个被其余进程set的item。
memcached 1.2.5以及更高版本,提供了gets和cas命令,它们能够解决上面的问题。若是您使用gets命令查询某个key的item,memcached会给您返回该item当前值的惟一标识。若是您覆写了这个item并想把它写回到memcached中,您能够经过cas命令把那个惟一标识一块儿发送给memcached。若是该item存放在memcached中的惟一标识与您提供的一致,您的写操做将会成功。若是另外一个进程在这期间也修改了这个item,那么该item存放在memcached中的惟一标识将会改变,您的写操做就会失败。
一般,基于memcached中item的值来修改item,是一件棘手的事情。除非您很清楚本身在作什么,不然请不要作这样的事情。
最后更新时间 2009-04-10 更新人 dormando@rydia.net
这里收集了常常被问到的关于memcached的问题
性能方面的问题
Memcached没有个人数据库快,为何?
在一对一比较中,memcached可能没有您的SQL查询快。可是,这不是memcached的设计目标。Memcached的目标是可伸缩性。当链接和请求增长的时候,memcached的性能将比大多数数据库好。您能够先在高负载的环境(并发的链接和请求)中测试您的代码,而后再决定memcached是否适合您。
客户端库
memcached有哪些客户端库?
看看上面的"如何访问memcached"小节。
使用不一样的客户端库,能够访问到memcached中相同的数据吗?
从技术上说,是能够的。可是您可能会遇到下面三个问题:
一致性哈希算法是a new approach to managing the first-layer hashing system for memcached clients。这里有一篇文章很好地解释了它的用处:http://www.last.fm/user/RJ/journal/2007/04/10/392555 。
目前有一些记录:
客户端能够经过"前缀"来给key设置一个域(命名空间)。例如,在一个共享主机的环境中,您能够将客户姓名做为"前缀",为key建立一个特定的域。在存储数据的时候,"前缀"能够用在key上,可是不该该参与哈希计算。目前,memcached本身尚未实现针对复杂结构数据的序列化方法,JSON则是一种被普遍使用的对象序列化格式。
最后更新时间 2009-04-10 更新人 dormando@rydia.net
这里收集了常常被问到的关于memcached的问题
若是您想要学习memcached的选项,在命令行下运行"memcached -h"便可。这个命令将会显示一个简单的选项说明。您能够随便试试这些选项,看看他们的功能。
另外,memcached发行版中还带有一个memcached(1)的man帮助页。
memcached采用了一种"懒过时"的策略,这种策略不消耗额外的CPU时间去专门处理过时的item。当一个item被请求(get命令)时,memcached会检查这个item的过时时间;若是已通过期,这个item将不会被返回给客户端。
一样,向cache中添加一个item时,若是cache已经满了,memcached首先替换已通过期的条目,而后替换最近未使用的item(the least used item, LRU淘汰算法)。
memcached不支持命名空间。可是有一些方法能够模拟命名空间。
若是您想为不一样类型的数据避免key冲突,能够给key添加一个有意义的字符串做为前缀。例如:"user_12345", "article_76890"。
尽管memcached不支持任何类型的通配符删除(wildcard deleting)或根据命名空间删除(deletion by namespace, 由于根本就没有命名空间),这里仍是有一些技巧来模拟它们。不过这些技巧须要走点弯路。
例如,在PHP中,以foo做为命名空间: