这里收集了经常被问到的关于memcached的问题
一般的问题
什么是memcached? memcached是一个高性能的、分布式的、内存对象缓存系统。memcached本质上是一个通用的缓存系统,但是它通常被用来减小数据库的负载,以达到加速dynamic web应用的目的。
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可以帮您显著地减小数据库负载。
Memcached同样适用在其他很多场合。至于到底适用哪些场合,您可以通读Memcached FAQ和相关的指南来获得一些灵感。如果您的数据库负载比较低但CPU使用率很高,您可以缓存计算好的结果( computed objects )和渲染后的模板(enderred templates)。通过memcached,您可以缓存session数据、临时数据以减少对他们的数据库写操作,缓存一些很小但是被频繁访问的文件, 缓存Web 'services'(非IBM宣扬的Web Services,译者注)或RSS feeds的结果...
即使您的资源(CPU、内存、数据库等,译者注)很充足,memcached至少也可以帮您加快页面的渲染速度。
什么情况下不适合适用memcached? 参见这里 。(下面也翻译这个页面)
Memcached的确很棒!但也不是每种场合都适用...
- 对象的大小大于1MB
- Memcached本身就不是为了处理庞大的多媒体(large media)和巨大的二进制块(streaming huge blobs)。
- 考虑其他的条件:http://www.danga.com/mogilefs
- key的长度大于250字符
- 如果真的用了这么长的key,那么您什么地方可能做错了。
- 还有,可以看看关于key长度的邮件列表。
- 您的虚拟主机不让您运行memcached
- 如果您的应用托管在低端的虚拟私有服务器(virtual private server, a slice of a machine)上,像vmware, xen这类虚拟化技术并不适合运行memcached。Memcached确实需要接管和控制大块的内存--如果memcached的内存被OS或 hypervisor交换出去,memcached的性能将大打折扣。
- 您的应用运行在不安全的环境中
- 记住,任何人仅仅通过telnet就可以访问到您的memcached。如果您的应用运行在共享的系统上,要盯紧哦!
- 您需要持久化数据,或者说您需要的应该是database
- 如果您仅仅期待memcached提供SQL接口,那么您可能需要重新思考一下对cache和memcached的理解。如果想对这个问题有更多的了解,庆参考下面dormando写的blog。
- links
- 2008/08
- Memcached versus more rdbms sharding at highscalability.com
- Should you use memcached? Should you just shard mysql more? by dormando
- 2008/08
怎么访问memcached?
一般来说,您的应用可以使用memcached的客户端库来访问一个或多个memcached。
这个客户端页面上列出了所有可用的API库,包括Perl, C, C#, PHP, Python, Java, Ruby, PostgreSQL的存储过程及触发器。
您可以根据memcached协议 编写自己的客户端库。
怎么把memcached当成database使用?
如果您想把memcached用作数据存储媒介而不是缓存,那么您应该使用database。MySQL Cluster拥有一些与memcached类似的特性(尽管MySQL Cluster安装并不容易),而且MySQL Cluster完全可以胜任一个可靠的分布存储媒介。
能够遍历memcached中所有的item吗?
不!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是怎么工作的?
- memcached最大的优势是什么?
- memcached和MySQL的query cache相比,有什么优缺点?
- memcached和服务器的local cache(比如PHP的APC、mmap文件等)相比,有什么优缺点?
- memcached的cache机制是怎样的?
- memcached如何实现冗余机制?
- memcached如何处理容错的?
- 如何将memcached中item批量导入导出?
- 但是我确实需要把memcached中的item都dump出来,确实需要把数据load到memcached中,怎么办?
- memcached是如何做身份验证的?
- 如何使用memcached的多线程是什么?如何使用它们?
- memcached能接受的key的最大长度是多少?(250bytes)
- memcached对item的过期时间有什么限制?(为什么有30天的限制?)
- memcached最大能存储多大的单个item?(1M byte)
- 为什么单个item的大小被限制在1M byte之内?
- 为了让memcached更有效地使用服务器的内存,可以在各个服务器上配置大小不等的缓存空间吗?
- 什么是binary协议?它值得关注吗?
- memcached是如何分配内存的?为什么不用malloc/free!?究竟为什么使用slab呢?
- memcached能保证数据存储的原子性吗?
集群架构方面的问题
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之间没有相互通信,因此不会增加 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服务器都会受益。
- 当您修改表时,MySQL的query cache会立刻被刷新(flush)。存储一个memcached item只需要很少的时间,但是当写操作很频繁时,MySQL的query cache会经常让所有缓存数据都失效。
- 在多核CPU上,MySQL的query cache会遇到扩展问题(scalability issues)。在多核CPU上,query cache会增加一个全局锁(global lock), 由于需要刷新更多的缓存数据,速度会变得更慢。
- 在MySQL的query cache中,我们是不能存储任意的数据的(只能是SQL查询结果)。而利用memcached,我们可以搭建出各种高效的缓存。比如,可以执行多个独立的查询,构建出一个用户对象(user object),然后将用户对象缓存到memcached中。而query cache是SQL语句级别的,不可能做到这一点。在小的网站中,query cache会有所帮助,但随着网站规模的增加,query cache的弊将大于利。
- query cache能够利用的内存容量受到MySQL服务器空闲内存空间的限制。给数据库服务器增加更多的内存来缓存数据,固然是很好的。但是,有了memcached,只要您有空闲的内存,都可以用来增加memcached集群的规模,然后您就可以缓存更多的数据。
memcached和服务器的local cache(比如PHP的APC、mmap文件等)相比,有什么优缺点?
首先,local cache有许多与上面(query cache)相同的问题。local cache能够利用的内存容量受到(单台)服务器空闲内存空间的限制。不过,local cache有一点比memcached和query cache都要好,那就是它不但可以存储任意的数据,而且没有网络存取的延迟。
- local cache的数据查询更快。考虑把highly common的数据放在local cache中吧。如果每个页面都需要加载一些数量较少的数据,考虑把它们放在local cached吧。
- local cache缺少集体失效(group invalidation)的特性。在memcached集群中,删除或更新一个key会让所有的观察者觉察到。但是在local cache中, 我们只能通知所有的服务器刷新cache(很慢,不具扩展性),或者仅仅依赖缓存超时失效机制。
- local cache面临着严重的内存限制,这一点上面已经提到。
memcached的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节点失效的情况下,集群没有必要做任何容错处理。如果发生了节点失效,应对的措施完全取决于用户。节点失效时,下面列出几种方案供您选择:
- 忽略它! 在失效节点被恢复或替换之前,还有很多其他节点可以应对节点失效带来的影响。
- 把失效的节点从节点列表中移除。做这个操作千万要小心!在默认情况下(余数式哈希算法),客户端添加或移除节点,会导致所有的缓存数据不可用!因为哈希参照的节点列表变化了,大部分key会因为哈希值的改变而被映射到(与原来)不同的节点上。
- 启动热备节点,接管失效节点所占用的IP。这样可以防止哈希紊乱(hashing chaos)。
- 如果希望添加和移除节点,而不影响原先的哈希结果,可以使用一致性哈希算法(consistent hashing)。您可以百度一下一致性哈希算法。支持一致性哈希的客户端已经很成熟,而且被广泛使用。去尝试一下吧!
- 两次哈希(reshing)。当客户端存取数据时,如果发现一个节点down了,就再做一次哈希(哈希算法与前一次不同),重新选择另一个节点(需要注意的时,客户端并没有把down的节点从节点列表中移除,下次还是有可能先哈希到它)。如果某个节点时好时坏,两次哈希的方法就有风险了,好的节点和坏的节点上都可能存在脏数据(stale data)。
如何将memcached中item批量导入导出?
您不应该这样做!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分钟),您可以考虑重新使用数据库。这里给出一些提示:
- 使用MogileFS(或者CouchDB等类似的软件)在存储item。把item计算出来并dump到磁盘上。MogileFS可以很方便地覆写item,并提供快速地访问。.您甚至可以把MogileFS中的item缓存在memcached中,这样可以加快读取速度。 MogileFS+Memcached的组合可以加快缓存不命中时的响应速度,提高网站的可用性。
- 重新使用MySQL。MySQL的 InnoDB主键查询的速度非常快。如果大部分缓存数据都可以放到VARCHAR字段中,那么主键查询的性能将更好。从memcached中按key查询几乎等价于MySQL的主键查询:将key 哈希到64-bit的整数,然后将数据存储到MySQL中。您可以把原始(不做哈希)的key存储都普通的字段中,然后建立二级索引来加快查询...key被动地失效,批量删除失效的key,等等。
上面的方法都可以引入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.html http://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,是一件棘手的事情。除非您很清楚自己在做什么,否则请不要做这样的事情。
Memcached FAQ(3) 性能和客户端库方面的问题 收藏
最后更新时间 2009-04-10 更新人 dormando@rydia.net 这里收集了经常被问到的关于memcached的问题
- 性能方面的问题
-
客户端库方面的问题
- memcached有哪些客户端库?
- 使用不同的客户端库,能够访问到memcached中相同的数据吗? (不同客户端库的可以协作吗?)
- 什么是一致性哈希的客户端?
- 客户端FAQ
性能方面的问题
Memcached没有我的数据库快,为什么? 在一对一比较中,memcached可能没有您的SQL查询快。但是,这不是memcached的设计目标。Memcached的目标是可伸缩性。当连接和请求增加的时候,memcached的性能将比大多数数据库好。您可以先在高负载的环境(并发的连接和请求)中测试您的代码,然后再决定memcached是否适合您。
客户端库
memcached有哪些客户端库? 看看上面的"如何访问memcached"小节。
使用不同的客户端库,可以访问到memcached中相同的数据吗? 从技术上说,是可以的。但是您可能会遇到下面三个问题:
- 不同的库采用不同的方式序列化数据。举个例子,perl的Cache::Memcached使用Storable来序列化结构复杂的数据(比如hash references, objects, 等)。其他语言的客户端库很可能不能读取这种格式的数据。如果您要存储复杂的数据并且想被多种客户端库读取,那么您应该以简单的string格式来存储,并且这种格式可以被JSON、XML等外部库解析。
- 同样,从某个客户端来的数据被压缩了,从另一个客户端来的却没被压缩。
- 各个客户端库可能使用不同的哈希算法(阶段一哈希)。在连接到多个memcached服务器端的情况下,客户端库根据自身实现的哈希算法把key映射到某台memcached上。正是因为不同的客户端库使用不同的哈希算法,所以被Perl客户端库映射到memcached A的key,可能又会被Python客户端库映射到memcached B,等等。Perl客户端库还允许为每台memcached指定不同的权重(weight),这也是导致这个问题的一个因素。
什么是一致性哈希的客户端?
一致性哈希算法是a new approach to managing the first-layer hashing system for memcached clients。这里有一篇文章很好地解释了它的用处:http://www.last.fm/user/RJ/journal/2007/04/10/392555 。
客户端FAQ
目前有一些记录: 客户端可以通过"前缀"来给key设置一个域(命名空间)。例如,在一个共享主机的环境中,您可以将客户姓名作为"前缀",为key创建一个特定的域。在存储数据的时候,"前缀"可以用在key上,但是不应该参与哈希计算。目前,memcached自己还没有实现针对复杂结构数据的序列化方法,JSON则是一种被广泛使用的对象序列化格式。
最后更新时间 2009-04-10 更新人 dormando@rydia.net 这里收集了经常被问到的关于memcached的问题
memcached的选项
如果您想要学习memcached的选项,在命令行下运行"memcached -h"即可。这个命令将会显示一个简单的选项说明。您可以随便试试这些选项,看看他们的功能。
另外,memcached发行版中还带有一个memcached(1)的man帮助页。
Item的过期
过期的item什么时候才会从cached中删除?
memcached采用了一种"懒过期"的策略,这种策略不消耗额外的CPU时间去专门处理过期的item。当一个item被请求(get命令)时,memcached会检查这个item的过期时间;如果已经过期,这个item将不会被返回给客户端。
同样,向cache中添加一个item时,如果cache已经满了,memcached首先替换已经过期的条目,然后替换最近未使用的item(the least used item, LRU淘汰算法)。
命名空间
memcached不支持命名空间。但是有一些方法可以模拟命名空间。
使用key的"前缀"来模拟命名空间
如果您想为不同类型的数据避免key冲突,可以给key添加一个有意义的字符串作为前缀。例如:"user_12345", "article_76890"。
根据命名空间来删除
尽管memcached不支持任何类型的通配符删除(wildcard deleting)或根据命名空间删除(deletion by namespace, 因为根本就没有命名空间),这里还是有一些技巧来模拟它们。不过这些技巧需要走点弯路。
例如,在PHP中,以foo作为命名空间:
- $ns_key = $memcache->get("foo_namespace_key");
- // if not set, initialize it
- if($ns_key===false) $memcache->set("foo_namespace_key", rand(1, 10000));
- // cleverly use the ns_key
- $my_key = "foo_".$ns_key."_12345";
- $my_val = $memcache->get($my_key);
- //To clear the namespace do:
- $memcache->increment("foo_namespace_key");