??xml version="1.0" encoding="utf-8" standalone="yes"?>
]]>
关键?Keys
命oCommands
时旉 Expiration times
错误信息 Error strings
存储命o Storage commands
d命o Retrieval command
删除 Deletion
增加/减少 Increment/Decrement
l计 Statistics
多用途统?nbsp;General-purpose statistics
其他命o Other commands
UDP协议 UDP protocol
memcached的客L通过TCPq接与服务器通信Q?/span>UDP协议的接口也可以使用Q详l说明请参?/span>”UDP 协议”部分Q。一个给定的q行中的memcached服务器在某个Q可配置的)端口上监听连接;客户端连接该端口Q发送命令给服务器,d反馈Q最后关闭连接?/span>
没有必要发送一个专门的命oȝ束会话。客L可以在不需要该q接的时候就关闭它。注意:我们鼓励客户端缓存它们与服务器的q接Q而不是每ơ要存储或读取数据的时候再ơ重新徏立与服务器的q接?/span>memcache同时打开很多q接不会Ҏ能造成到大的媄响,q是因ؓmemcache在设计之处,p设计成即使打开了很多连接(数百或者需要时上千个连接)也可以高效的q行。缓存连接可以节省与服务器徏?/span>TCPq接的时间开销Q于此相比,在服务器Dؓ建立一个新的连接所做准备的开销可以忽略不计Q?/span>
memcache通信协议有两U类型的数据Q文本行和非l构化数 据。文本行用来发送从客户端到服务器的命o以及从服务器回送的反馈信息。非l构化的数据用在客户端希望存储或者读取数据时。服务器会以字符的形式严格? 的q回相应数据在存储时存储的数据。服务器不关注字节序Q它也不知道字节序的存在?/span>memcahce寚wl构化数据中的字W没有Q何限Ӟ可以是Q意的字符Q读取数据时Q客L可以在前ơ返回的文本行中切的知道接下来的数据块的长度?/span>
文本行通常?#8220;"r"n”l束。非l构化数据通常也是?#8220;"r"n”l束Q尽?/span>"r?/span>"n或者其他Q?/span>8位字W可以出现在数据块中。所以当客户端从服务器读取数据时Q必M用前面提供的数据块的长度Q来定数据的l束Q二不是依据跟随在字W流N?#8220;"r"n”来确定数据流的结束,管实际上数据流格式如此?/span>
memcached使用关键字来区分存储不同的数据。关键字是一个字W串Q可以唯一标识一条数据。当前关键字的长度限制是250个字W(当然目前客户端似乎没有需求用q么长的关键字)Q关键字一?span style="color: red;">不能包含控制字符?span style="color: red;">I格?/span>
memcahe?/span>3U类型的命oQ?/span>
l 存储命o?span style="font-family: 宋体;">Q?/span>3个命令:set?/span>add?/span>replaceQ要求服务器安装关键字存储数据。客L发送一个命令行Q然后一个数据块Q命令执行后客户端等待一行反馈,用来表示命o执行成功与否?/span>
l d命o-- Q只?/span>1个命令:getQ? 要求服务器根据一l关键字d数据Q在一个请求d以包含一个或多个关键字)。客L发送一个包含请求关键字的命令行Q命令传递到服务器后Q服务器查? 每一个关键字下的数据Q然户将数据?#8220;一个关键字数据Q一个反馈信息行跟着一个数据块”的格式回送数据,直到服务器发?#8220;END”的反馈行?/span>
l 其他命oQ如flush_allQ?/span>version{。这些命令不使用非结构化的数据。对于这些命令,客户端发送一个文本的命o行,Ҏ命o的特性等待一行数据或者在最后一行以“END“l尾的几行反馈信息?/span>
所有的命o行L以命令的名字开始,紧接着是以I格分割的参数。命令名U都是小写,q且是大写敏感的?/span>
一些发送到服务器的命o包含时旉Q该时旉对应于:数据保存时_客户端操作限Ӟ。在q些例子中,被发送的真实旉要么?/span>UNIX旉戻I?/span>1970q?/span>1?/span>1?/span>零时LU数数|Q或者从当前旉开始算LU数。对于后一U情况,U数的数g能超q?/span>60*60*24*30Q?/span>30天的U数Q;如果U数的数值大于了q个数|服务器会认ؓ该数值是UNIX旉戻I而不是自当前旉开始的U数偏移倹{?/span>
每个命o都有可能被反馈以一个错误消息。这些错误消息有以下三个cdQ?/span>
l “ERROR"r"n”
意味着客户端发送了一个在协议中不存在的命令?/span>
l "CLIENT_ERROR <error>"r"n"
表示客户端输入的命o行上存在某种错误Q输入不W合协议规定?/span><error>是一个h工可读(human-readableQ的错误注释?/span>
l "SERVER_ERROR <error>"r"n"
表示服务器在执行命o时发生了某些错误Q致使服务器无法执行下去?/span><error>也是一个h工可读(human-readableQ的错误注释。在一些情况下Q错误导致服务器不能再ؓ客户端服务(q样的情况很发生)Q服务器׃在发生错误消息后d关闭q接?span style="color: red;">q也是服务器d关闭到客Lq接的唯一情况?/span>
后箋U数各种命o的时候,我们不再赘述错误消息的情况,当我们要清楚错误是存在的Q不可忽略?/span>
首先Q客L发生如下q样的命令:
<command name> <key> <flags> <exptime> <bytes>"r"n <data block>"r"n |
其中Q?/span>
<command name> ?/span> set?/span>add或?/span>replace?/span>set表示存储该数据;add表示如果服务器没有保存该关键字的情况下,存储该数据;replace表示在服务器已经拥有该关键字的情况下Q替换原有内宏V?/span>
<key>是客L要求服务器存储数据的关键字?/span>
<flags>是一?/span>16位的无符h敎ͼ服务器将它和数据一起存储ƈ且当该数据被索时一赯回。客L可能使用该数gZ个位图来存储Ҏ数据信息Q这个字D对服务器不是透明的?/span>
<exptime>是超时时间。如果gؓ0表示该数据项永远不超Ӟ但有时候该数据可能被删除以ؓ其他数据腑ևI间Q;如果g?/span>0Q可能是l对?/span>UNIX旉Q也可能是自现在开始的偏移|它保证客h在这个超时时间到辑Q客L取不到该数据项?/span>
<bytes>是随后数据的字节敎ͼ不包括终l符”"r"n”?/span><bytes>有可能是0Q它后面是一个空的数据块?/span>
<data block>是真正要存储数据?/span>
发送命令行和数据后Q客L{待反馈Q可以是如下几种情况Q?/span>
l "STORED"r"n" 表示存储数据成功?/span>
l "NOT_STORED"r"n" 表示发送的数据没有存储Q但q不因ؓ错误Q而是发生?/span>add或?/span>replace命o不能满条gӞ或者数据项正处于要删除的队列中?/span>
l 错误消息
d命o如下所C:
get <key>*"r"n |
<key>*表示一个或多个使用I格分割的关键字字符丌Ӏ?/span>
发送命令后Q客L{待q回一个或多个数据,每个数据的格式是一个文本行Q后跟着一个数据块。当所有的数据发送完毕后Q服务器发送字W串”END"r"n”表示服务器反馈数据的l束?/span>
q回数据的格式如下Q?/span>
VALUE <key> <flags> <bytes>"r"n <data block>"r"n |
<key>是发生数据项的关键字?/span>
<flags>是存储该数据ҎQ客L命o中的标志字段?/span>
<bytes>是紧跟文本行后数据块的长度,不包括终l符”"r"n”?/span>
<data block>是数据项的数据部分?/span>
如果h命o行中的有些关键字对应的数据项没有被返回,q意味着服务器没有该关键字标CZ的数据项Q有可能是从来没有被存储q,或者存储过但被删除掉以腑և内存I间Q或者数据项时了,再或者它被某个客L删除了)?/span>
删除命o允许直接删除数据,命o格式如下Q?/span>
delete <key> <time>"r"n |
<key>是客L希望服务器删除数据项的关键字
<time>是客L希望服务器阻?/span>add?/span>replace命o使用该关键字数据的U数Q可以是相对旉也可以是UNIX的绝Ҏ间。在q段旉内,数据被攑օ一个删除队列,它不能被get命odQ在其上使用add?/span>replace也会p|Q但使用set命o可以成功。当q个旉q去后,数据从服务器的内存中真正的删除。该参数是可选参敎ͼ如果不存在默认ؓ0Q这意味着立即从服务器上删除?/span>
服务器返回信息:
l "DELETED"r"n" 表示数据删除成?/span>
l "NOT_FOUND"r"n" 表示该关键字指定的数据项在服务器上没有找?/span>
l 其他错误消息
下面?/span>flush_all命o使得所有存在的数据立卛_效?/span>
“incr”?/span>”decr”命o用来修改以及存在的数据项的内容,增加或者减它。该数据被当?/span>32位无W号整数处理。如果当前数据非此类数据Q则l将该内容当?/span>0来处理。另外在其上施加incr/decr命o的数据项必须是业已存在的Q对于不存在的数据项不会它作ؓ0对待Q而是以错误结束?/span>
客户端发送命令行如下格式Q?/span>
incr <key> <value>"r"n 或?/span> decr <key> <value>"r"n |
<key>是客L要修Ҏ据项的关键字
<value>是对该数据行q行增加或者减的操作数。它是一?/span>32位的无符h数?/span>
反馈信息有如下几U:
l "NOT_FOUND"r"n"
表明在服务器上没有找到该数据V?/span>
l "<value>"r"n "
value是执行完增加/减少命o后,该数据项新的数倹{?/span>
l 错误信息?/span>
注意?#8220;decr”命o的下溢问题,如果客户端尝试减的数量于0Q其l果?/span>0?#8220;incr”命o的溢出问题没有检查。另外减一个数据而它减了长度Q但不保证减它q回时的长度。该数字可能是附加空格的数字Q但q只是实现的优化Q所以你不能怿它?/span>
“stats”命o用来查询服务器的q行情况和其他内部数据。它有两U情况,以有无参数来区分Q?/span>
stats"r"n 或?/span> stats <args>"r"n |
W一U情况它D服务器输Z般统计信息以及设|信息和文档化内宏V?/span>
W二U情冉|?/span><args>具体的参敎ͼ服务器发送各U内部数据。这部分没有在协议中文档化,因ؓ?/span>memcache的开发者有兛_可能是随时变化的?/span>
当接收到没有带参数的“stats”命o后,服务器发送许多类g如下格式的文本行Q?/span>
STAT <name> <value>"r"n |
当类似的文本行全部发送完毕后Q服务器发送如下的文本行结束反馈信息:
END"r"n |
在所?/span>STAT文本行中Q?/span><name>是该l计目的名Uͼ<value>是其数据。下面是一?/span>stats命o反馈的所有统计项目的列表Q后面跟着其值的数据cd。在数据cd列中Q?/span>”32u”表示一?/span>32位无W号整数Q?/span>”64u”表示一?/span>64位无W号整数Q?/span>”32u:32u”表示是两个用冒号分割?/span>32位无W号整数?/span>
名称 |
值类?/span> |
含义 |
pid |
32u |
服务器进E的q程?/span> |
uptime |
32u |
服务器自q行以来的秒?/span> |
time |
32u |
当前服务器上?/span>UNIX旉 |
version |
string |
服务器的版本字符?/span> |
rusage_user |
32u:32u |
服务器进E积累的用户旉Q秒:微妙Q?/span> |
rusage_system |
32u:32u |
服务器进E积累的pȝ旉Q秒:微妙Q?/span> |
curr_items |
32u |
当前在服务器上存储的数据的个数 |
total_items |
32u |
在服务器上曾l保存过的数据项的个?/span> |
bytes |
64u |
当前服务器上保存数据的字节数 |
curr_connections |
32u |
处于打开状态的q接数目 |
total_connections |
32u |
曄打开q的所有连接的数目 |
connection_structures |
32u |
服务器分配的q接l构体的个数 |
cmd_get |
64u |
get命oh的次?/span> |
cmd_set |
64u |
存储命oh的次?/span> |
get_hits |
64u |
关键字获取命中的ơ数 |
get_misses |
64u |
关键字获取没有命中的ơ数 |
evictions |
64u |
所有因时而被替换出内存的数据的个数 |
bytes_read |
64u |
服务器从|络上读取到的字节数 |
bytes_write |
64u |
服务器向|络上写的字节数 |
limit_maxbytes |
64u |
服务器允许存储数据的最大?/span> |
"flush_all"是一个带有可选数字参数的命oQ它的执行L成功的,服务器L响应?/span>"OK"r"n"字符丌Ӏ它的作用是使得所有的数据立卻I默认Q或者经q一个指定的时旉后全部失效。在|数据项失效后,对于d命o不会返回Q何内容,除非在失效后q些数据再次被存储?/span>flush_allq没有真正的释放q些存在q的数据占用的内存I间Q数据空间真实被占用的情况发生在使用新的数据覆盖老的数据Ҏ。该命o作用最准确的定义是Q它D所有更新时间早于该命o讑֮的时间点的数据项Q在被检索时被忽略,其表现就像已被删除了一栗?/span>
使用带有延时flush_all命o的目的是Q当你有?/span>memcached服务器池Q需要刷新所有的内容Ӟ但不能在同一旉h所有的服务器,q样可能因为所有的服务器突焉要重新徏立数据内容,而导致数据库压力的颠。g旉项允许你设|他们隔10U失效(讄W一个g时ؓ0Q第二个10U,W三?/span>20U等{)?/span>
"version"是一个没有参数的命oQ命令格式如下:
version"r"n |
服务器发回的反馈信息如下Q?/span>
l "VERSION <version>"r"n"
<version>是从服务器返回的版本字符丌Ӏ?/span>
l 错误消息?/span>
"verbosity"是一个带有数字参数的命o。它的执行L成功的,服务器反馈以"OK"r"n"表示执行完成。它用来讄日志输出的详l等U?/span>
"quit"是一个没有参数的命o。其格式如下Q?/span>
quit"r"n |
当服务器接受到此命o后,关闭与该客Lq接。不怎样Q客L可以在Q意不需要该q接的时d闭它Q而不需要发送该命o?/span>
当基?/span>TCP协议的连接数过TCPq接的上限时Q我们可以?/span>UDP协议来替代。但?/span>UDP协议接口不提供可靠的传输Q所以多用在不严D求成功的操作上;典型?/span>geth会因为缓存的问题Q引起丢失或者不完整的传输?/span>
每个UDP数据包包含一个简单的帧头Q接着是?/span>TCP协议描述的数据格式的数据。在当前的实CQ请求必d含在一个单独的UDP数据包中Q但q回可能分散在多个数据包中。(唯一的可以拆分请求数据包的是大的多关键字geth?/span>sethQ鉴于可靠性相比而言他们更适合?/span>TCP传输。)
帧头?/span>8字节长,如下是其格式Q所有的数字都是16位网l字节序整ŞQ高位在前)Q?/span>
0 - 1 hID
2 - 3 序列?/span>
4 - 5 在当前的消息中含有的数据包的个数
6-7 保留以后使用Q当前必Mؓ0
hID由客L提供。它的典型值是一个从随机U子开始递增|实际上客L可以使用L的请?/span>ID。服务器的反馈信息中包含了和h命o中一LhID。客L凭借这个请?/span>ID区分来自于同一服务器的反馈。每一个包含未知请?/span>ID的数据包Q可能是׃延时反馈造成Q这些数据包都应该抛弃不用?/span>
序列号从0?/span>n-1Q?/span>n是消息中ȝ数据包的个数。客L按照序列h序重l数据包Q结果序列中包含了一个完整的?/span>TCP协议一h式的反馈信息Q包含了“"r"n”ȝ字符Ԍ?/span>
发表日:2008/7/30
作者:镉K雅广(Masahiro Nagano)
原文链接Q?a >http://gihyo.jp/dev/feature/01/memcached/0005
我是Mixi的长野。memcached的连载终于要l束了。到上次为止Q我们介l了与memcached直接相关的话题,本次介绍一些mixi的案例和实际应用上的话题Qƈ介绍一些与memcached兼容的程序?
mixi在提供服务的初期阶段׃用了memcached。随着|站讉K量的急剧增加Q单Uؓ数据库添加slave已无法满需要,因此引入了memcached。此外,我们也从增加可扩展性的斚wq行了验证,证明了memcached的速度和稳定性都能满需要。现在,memcached已成为mixi服务中非帔R要的l成部分?/p>
? 现在的系l组?/p>
mixi使用了许许多多服务器Q如数据库服务器、应用服务器、图片服务器、反向代理服务器{。单单memcached有近200台服务器在运行?memcached服务器的典型配置如下Q?/p>
q些服务器以前曾用于数据库服务器{。随着CPU性能提升、内存hg降,我们U极地将数据库服务器、应用服务器{换成了性能更强大、内存更多的服务器。这P可以抑制mixi整体使用的服务器数量的急剧增加Q降低管理成本。由于memcached服务器几乎不占用CPUQ就换下来的服务器用作memcached服务器了?/p>
每台memcached服务器仅启动一个memcachedq程。分配给memcached的内存ؓ3GBQ启动参数如下:
/usr/bin/memcached -p 11211 -u nobody -m 3000 -c 30720
׃使用了x86_64的操作系l,因此能分?GB以上的内存?2位操作系l中Q每个进E最多只能?GB内存。也曄考虑q启动多个分?GB以下内存的进E,但这样一台服务器上的TCPq接数就会成倍增加,理上也变得复杂Q所以mixiq一使用?4位操作系l?/p>
另外Q虽然服务器的内存ؓ4GBQ却仅分配了3GBQ是因ؓ内存分配量超q这个|有可能D内存交换(swap)。连载的W??/a>中前坂讲解过了memcached的内存存?#8220;slab allocator”Q当时说q,memcached启动时指定的内存分配量是memcached用于保存数据的量Q没有包?#8220;slab allocator”本n占用的内存、以及ؓ了保存数据而设|的理I间。因此,memcachedq程的实际内存分配量要比指定的容量要大,q一点应当注意?/p>
mixi保存在memcached中的数据大部分都比较。这Pq程的大要比指定的定w大很多。因此,我们反复改变内存分配量进行验证,认?GB的大不会引发swapQ这是现在应用的数倹{?/p>
Z方便阅读Q现原来的译l果打包成PDF文档Q?a >下蝲memcached使用Ҏ和客L
发表日:2008/7/23
作者:镉K雅广(Masahiro Nagano)
原文链接Q?a >http://gihyo.jp/dev/feature/01/memcached/0004
我是Mixi的长野?W??/a>?W??/a> 由前坂介l了memcached的内部情c本ơ不再介lmemcached的内部结构,开始介lmemcached的分布式?/p>
正如W??/a>中介l的那样Q?memcached虽然UCؓ“分布?#8221;~存服务器,但服务器端ƈ没有“分布?#8221;功能。服务器端仅包括 W??/a>?W??/a> 前坂介绍的内存存储功能,其实现非常简单。至于memcached的分布式Q则是完全由客户端程序库实现的。这U分布式是memcached的最大特炏V?/p>
q里多次使用?#8220;分布?#8221;q个词,但ƈ未做详细解释。现在开始简单地介绍一下其原理Q各个客L的实现基本相同?/p>
下面假设memcached服务器有node1~node3三台Q应用程序要保存键名?#8220;tokyo”“kanagawa”“chiba”“saitama”“gunma” 的数据?/p>
? 分布式简介:准备 首先向memcached中添?#8220;tokyo”。将“tokyo”传给客户端程序库后,客户端实现的法׃Ҏ“?#8221;来决定保存数据的memcached服务器。服务器选定后,卛_令它保存“tokyo”及其倹{?/p>
? 分布式简介:d?/p>
同样Q?#8220;kanagawa”“chiba”“saitama”“gunma”都是先选择服务器再保存?/p>
接下来获取保存的数据。获取时也要要获取的键“tokyo”传递给函数库。函数库通过与数据保存时相同的算法,Ҏ“?#8221;选择服务器。用的法相同Q就能选中与保存时相同的服务器Q然后发送get命o。只要数据没有因为某些原因被删除Q就能获得保存的倹{?/p>
? 分布式简介:获取?/p>
q样Q将不同的键保存C同的服务器上Q就实现了memcached的分布式?memcached服务器增多后Q键׃分散Q即使一台memcached服务器发生故障无法连接,也不会媄响其他的~存Q系l依然能l箋q行?/p>
接下来介l?a >W??/a> 中提到的Perl客户端函数库Cache::Memcached实现的分布式Ҏ?/p>
Perl的memcached客户端函数库Cache::Memcached?memcached的作者Brad Fitzpatrick的作品,可以说是原装的函数库了?/p>
该函数库实现了分布式功能Q是memcached标准的分布式Ҏ?/p>
Cache::Memcached的分布式Ҏ单来_是“Ҏ服务器台数的余数q行分散”。求得键的整数哈希|再除以服务器台数Q根据其余数来选择服务器?/p>
下面Cache::Memcached化成以下的Perl脚本来进行说明?/p>
Cache::Memcached在求哈希值时使用了CRC?/p>
首先求得字符串的CRC|Ҏ该值除以服务器节点数目得到的余数决定服务器。上面的代码执行后输入以下结果: Ҏ该结果,“tokyo”分散到node2Q?#8220;kanagawa”分散到node3{。多说一句,当选择的服务器无法q接ӞCache::Memcached会将q接ơ数d到键之后Q再ơ计哈希值ƈ试q接。这个动作称为rehash。不希望rehash时可以在生成Cache::Memcached对象时指?#8220;rehash => 0”选项?/p>
余数计算的方法简单,数据的分散性也相当优秀Q但也有其缺炏V那是当添加或U除服务器时Q缓存重l的代h相当巨大。添加服务器后,余数׃产生巨变Q这样就无法获取与保存时相同的服务器Q从而媄响缓存的命中率。用Perl写段代码来验证其代h?/p>
q段Perl脚本演示了将“a”?#8220;z”的键保存到memcachedq访问的情况。将其保存ؓmod.plq执行?/p>
首先Q当服务器只有三台时Q?/p>
l果如上Qnode1保存a、c、d、e……Qnode2保存g、i、k……Q每台服务器都保存了8个到10个数据?/p>
接下来增加一台memcached服务器?/p>
d了node4。可见,只有d、i、k、p、r、y命中了。像q样Q添加节点后键分散到的服务器会发生巨大变化?6个键中只有六个在讉K原来的服务器Q其他的全都Ud了其他服务器。命中率降低?3%。在Web应用E序中用memcachedӞ在添加memcached服务器的瞬间~存效率会大q度下降Q负载会集中到数据库服务器上Q有可能会发生无法提供正常服务的情况?/p>
mixi的Web应用E序q用中也有这个问题,D无法dmemcached服务器。但׃使用了新的分布式ҎQ现在可以轻而易丑֜dmemcached服务器了。这U分布式ҎUCؓ Consistent Hashing?/p>
关于Consistent Hashing的思想Qmixi株式会社的开发blog{许多地斚w介绍q,q里只简单地说明一下?/p>
Consistent Hashing如下所C:首先求出memcached服务器(节点Q的哈希|q将光|到0?32的圆QcontinuumQ上。然后用同样的方法求出存储数据的键的哈希|q映到圆上。然后从数据映射到的位置开始顺旉查找Q将数据保存到找到的W一个服务器上。如果超q?32仍然找不到服务器Q就会保存到W一台memcached服务器上?/p>
? Consistent HashingQ基本原?/p>
从上囄状态中d一台memcached服务器。余数分布式法׃保存键的服务器会发生巨大变化而媄响缓存的命中率,但Consistent Hashing中,只有在continuum上增加服务器的地炚w时针方向的W一台服务器上的键会受到影响?/p>
? Consistent HashingQ添加服务器 因此QConsistent Hashing最大限度地抑制了键的重新分布。而且Q有的Consistent Hashing的实现方法还采用了虚拟节点的思想。用一般的hash函数的话Q服务器的映地点的分布非常不均匀。因此,使用虚拟节点的思想Qؓ每个物理节点Q服务器Q在continuum上分?00?00个点。这样就能抑制分布不均匀Q最大限度地减小服务器增减时的缓存重新分布?/p>
通过下文中介l的使用Consistent Hashing法的memcached客户端函数库q行试的结果是Q由服务器台敎ͼnQ和增加的服务器台数QmQ计增加服务器后的命中率计公式如下: (1 - n/(n+m)) * 100 本连载中多次介绍的Cache::Memcached虽然不支持Consistent HashingQ但已有几个客户端函数库支持了这U新的分布式法。第一个支持Consistent Hashing和虚拟节点的memcached客户端函数库是名为libketama的PHP库,由last.fm开发?/p>
至于Perl客户端,q蝲?a >W??/a> 中介l过的Cache::Memcached::Fast和Cache::Memcached::libmemcached支持 Consistent Hashing?/p>
两者的接口都与Cache::Memcached几乎相同Q如果正在用Cache::MemcachedQ那么就可以方便地替换过来。Cache::Memcached::Fast重新实现了libketamaQ用Consistent Hashing创徏对象时可以指定ketama_points选项?/p>
另外QCache::Memcached::libmemcached 是一个用了Brain Aker开发的C函数库libmemcached的Perl模块?libmemcached本n支持几种分布式算法,也支持Consistent HashingQ其Perll定也支持Consistent Hashing?/p>
本次介绍了memcached的分布式法Q主要有memcached的分布式是由客户端函数库实现Q以及高效率地分散数据的Consistent Hashing法。下ơ将介绍mixi在memcached应用斚w的一些经验,和相关的兼容应用E序?/p>
memcached的分布式
memcached的分布式是什么意思?
Cache::Memcached的分布式Ҏ
Ҏ余数计算分散
use strict;
use warnings;
use String::CRC32;
my @nodes = ('node1','node2','node3');
my @keys = ('tokyo', 'kanagawa', 'chiba', 'saitama', 'gunma');
foreach my $key (@keys) {
my $crc = crc32($key); # CRC?br />
my $mod = $crc % ( $#nodes + 1 );
my $server = $nodes[ $mod ]; # Ҏ余数选择服务?br />
printf "%s => %s\n", $key, $server;
}tokyo => node2
kanagawa => node3
chiba => node2
saitama => node1
gunma => node1Ҏ余数计算分散的缺?/h3>
use strict;
use warnings;
use String::CRC32;
my @nodes = @ARGV;
my @keys = ('a'..'z');
my %nodes;
foreach my $key ( @keys ) {
my $hash = crc32($key);
my $mod = $hash % ( $#nodes + 1 );
my $server = $nodes[ $mod ];
push @{ $nodes{ $server } }, $key;
}
foreach my $node ( sort keys %nodes ) {
printf "%s: %s\n", $node, join ",", @{ $nodes{$node} };
}$ mod.pl node1 node2 nod3
node1: a,c,d,e,h,j,n,u,w,x
node2: g,i,k,l,p,r,s,y
node3: b,f,m,o,q,t,v,z$ mod.pl node1 node2 node3 node4
node1: d,f,m,o,t,v
node2: b,i,k,p,r,y
node3: e,g,l,n,u,w
node4: a,c,h,j,q,s,x,zConsistent Hashing
Consistent Hashing的简单说?/h3>
支持Consistent Hashing的函数库
my $memcached = Cache::Memcached::Fast->new({
servers => ["192.168.0.1:11211","192.168.0.2:11211"],
ketama_points => 150
});ȝ
下面是《memcached全面剖析》的W三部分?/p>
发表日:2008/7/16
作者:前坂?Toru Maesaka)
原文链接Q?a >http://gihyo.jp/dev/feature/01/memcached/0003
memcached是缓存,所以数据不会永久保存在服务器上Q这是向pȝ中引入memcached的前提? 本次介绍memcached的数据删除机Ӟ以及memcached的最新发展方向——二q制协议QBinary ProtocolQ? 和外部引擎支持?/p>
上次介绍q, memcached不会释放已分配的内存。记录超时后Q客L无法再看见该记录(invisibleQ透明Q, 其存储空间即可重复用?/p>
memcached内部不会监视记录是否q期Q而是在get时查看记录的旉戻I查记录是否过期? q种技术被UCؓlazyQ惰性)expiration。因此,memcached不会在过期监视上耗费CPU旉?/p>
memcached会优先用已时的记录的I间Q但即如此Q也会发生追加新记录时空间不的情况Q? 此时p使用名ؓ Least Recently UsedQLRUQ机制来分配I间? 思义Q这是删?#8220;最q最?#8221;的记录的机制? 因此Q当memcached的内存空间不xQ无法从slab class 获取到新的空间时Q,׃最q未被用的记录中搜索,q将其空间分配给新的记录? 从缓存的实用角度来看Q该模型十分理想?/p>
不过Q有些情况下LRU机制反倒会造成ȝ。memcached启动旉过“-M”参数可以止LRUQ如下所C:
$ memcached -M -m 1024
启动时必L意的是,写?#8220;-m”选项是用来指定最大内存大的。不指定具体数值则使用默认?4MB?/p>
指定“-M”参数启动后,内存用尽时memcached会返回错误? 话说回来Qmemcached毕竟不是存储器,而是~存Q所以推荐用LRU?/p>
memcached的roadmap上有两个大的目标。一个是二进制协议的{划和实玎ͼ另一个是外部引擎的加载功能?/p>
使用二进制协议的理由是它不需要文本协议的解析处理Q得原本高速的memcached的性能更上一层楼Q? q能减少文本协议的漏z。目前已大部分实玎ͼ开发用的代码库中已包含了该功能? memcached的下载页面上有代码库的链接?/p>
协议的包?4字节的Q其后面是键和无l构数据QUnstructured DataQ? 实际的格式如下(引自协议文档Q:
Byte/ 0 | 1 | 2 | 3 |
/ | | | |
|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+
0/ HEADER /
/ /
/ /
/ /
+---------------+---------------+---------------+---------------+
24/ COMMAND-SPECIFIC EXTRAS (as needed) /
+/ (note length in th extras length header field) /
+---------------+---------------+---------------+---------------+
m/ Key (as needed) /
+/ (note length in key length header field) /
+---------------+---------------+---------------+---------------+
n/ Value (as needed) /
+/ (note length is total body length header field, minus /
+/ sum of the extras and key length body fields) /
+---------------+---------------+---------------+---------------+
Total 24 bytes
如上所C,包格式十分简单。需要注意的是,占据?6字节的头?HEADER)分ؓ h_Request HeaderQ和响应_Response HeaderQ两U? 头部中包含了表示包的有效性的Magic字节、命令种cR键长度、值长度等信息Q格式如下:
Request Header
Byte/ 0 | 1 | 2 | 3 |
/ | | | |
|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+
0| Magic | Opcode | Key length |
+---------------+---------------+---------------+---------------+
4| Extras length | Data type | Reserved |
+---------------+---------------+---------------+---------------+
8| Total body length |
+---------------+---------------+---------------+---------------+
12| Opaque |
+---------------+---------------+---------------+---------------+
16| CAS |
| |
+---------------+---------------+---------------+---------------+
Response Header
Byte/ 0 | 1 | 2 | 3 |
/ | | | |
|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+
0| Magic | Opcode | Key Length |
+---------------+---------------+---------------+---------------+
4| Extras length | Data type | Status |
+---------------+---------------+---------------+---------------+
8| Total body length |
+---------------+---------------+---------------+---------------+
12| Opaque |
+---------------+---------------+---------------+---------------+
16| CAS |
| |
+---------------+---------------+---------------+---------------+
如希望了解各个部分的详细内容Q可以checkout出memcached的二q制协议的代码树Q? 参考其中的docs文g夹中的protocol_binary.txt文档?/p>
看到HEADER格式后我的感xQ键的上限太大了Q现在的memcached规格中,键长度最大ؓ250字节Q? 但二q制协议中键的大用2字节表示。因此,理论上最大可使用65536字节Q?<sup>16</sup>Q长的键? 管250字节以上的键q不会太常用Q二q制协议发布之后可以用巨大的键了?/p>
二进制协议从下一版本1.3pd开始支持?/p>
我去q曾l试验性地memcached的存储层攚w成了可扩展的(pluggableQ?/p>
MySQL的Brian Aker看到q个攚w之后,将代码发到了memcached的邮件列表?
memcached的开发者也十分感兴,放Croadmap中。现在由我和
memcached的开发者Trond Norbye协同开发(规格设计、实现和试Q?
和国外协同开发时时差是个大问题,但抱着相同的愿景,
最后终于可以将可扩展架构的原型公布了?
代码库可以从memcached的下载页?/a>
上访问?/p>
世界上有许多memcached的派生YӞ其理由是希望怹保存数据、实现数据冗余等Q?
即牺牲一些性能也在所不惜。我在开发memcached之前Q在mixi的研发部也曾l?
考虑q重新发明memcached?/p>
外部引擎的加载机制能装memcached的网l功能、事件处理等复杂的处理?
因此Q现阶段通过强制手段或重新设计等方式使memcached和存储引擎合作的困难
׃烟消云散Q尝试各U引擎就会变得轻而易举了?/p>
该项目中我们最重视的是API设计。函数过多,会引擎开发者感到麻烦;
q于复杂Q实现引擎的门槛׃q高。因此,最初版本的接口函数只有13个?
具体内容限于幅Q这里就省略了,仅说明一下引擎应当完成的操作Q?/p>
对详l规格有兴趣的读者,可以checkout engine目的代码,阅读器中的engine.h?/p>
memcached支持外部存储的难ҎQ网l和事g处理相关的代码(核心服务器)?
内存存储的代码紧密关联。这U现象也UCؓtightly coupledQ紧密耦合Q?
必须内存存储的代码从核心服务器中独立出来,才能灉|地支持外部引擎?
因此Q基于我们设计的APIQmemcached被重构成下面的样子: 重构之后Q我们与1.2.5版、二q制协议支持版等q行了性能ҎQ证实了它不会造成性能影响?/p>
在考虑如何支持外部引擎加蝲Ӟ让memcachedq行q行控制Qconcurrency controlQ的Ҏ是最为容易的Q?
但是对于引擎而言Qƈ行控制正是性能的真谛,因此我们采用了将多线E支持完全交l引擎的设计Ҏ?/p>
以后的改q,会得memcached的应用范围更为广泛?/p>
本次介绍了memcached的超时原理、内部如何删除数据等Q在此之上又介绍了二q制协议?
外部引擎支持{memcached的最新发展方向。这些功能要?.3版才会支持,敬请期待Q?/p>
q是我在本连载中的最后一。感谢大安L的文章! 下次由长野来介绍memcached的应用知识和应用E序兼容性等内容?/p>
外部引擎支持的必要?/h3>
单API设计的成功的关键
重新审视现在的体p?/h3>
ȝ
下面是《memcached全面剖析》的W二部分?/p>
发表日:2008/7/9
作者:前坂?Toru Maesaka)
原文链接Q?a >http://gihyo.jp/dev/feature/01/memcached/0002
我是mixi株式会社研究开发组的前坂徹? 上次的文章介l了memcached是分布式的高速缓存服务器? 本次介lmemcached的内部构造的实现方式Q以及内存的理方式? 另外Qmemcached的内部构造导致的q也将加以说明?/p>
最q的memcached默认情况下采用了名ؓSlab Allocator的机制分配、管理内存? 在该机制出现以前Q内存的分配是通过Ҏ有记录简单地q行malloc和free来进行的? 但是Q这U方式会D内存片Q加重操作系l内存管理器的负担,最坏的情况下, 会导致操作系l比memcachedq程本nq慢。Slab Allocator是册问题而诞生的?/p>
下面来看看Slab Allocator的原理。下面是memcached文档中的slab allocator的目标:
the primary goal of the slabs subsystem in memcached was to eliminate memory fragmentation issues totally by using fixed-size memory chunks coming from a few predetermined size classes.
也就是说QSlab Allocator的基本原理是按照预先规定的大,分配的内存分割成特定长度的块, 以完全解军_存碎片问题?/p>
Slab Allocation的原理相当简单?分配的内存分割成各U尺寸的块(chunkQ, q把寸相同的块分成l(chunk的集合)Q图1Q?/p>
? Slab Allocation的构造图
而且Qslab allocatorq有重复使用已分配的内存的目的? 也就是说Q分配到的内存不会释放,而是重复利用?/p>
Page
分配lSlab的内存空_默认?MB。分配给Slab之后Ҏslab的大切分成chunk?/p>
Chunk
用于~存记录的内存空间?/p>
Slab Class
特定大小的chunk的组?/p>
下面说明memcached如何针对客户端发送的数据选择slabq缓存到chunk中?/p>
memcachedҎ收到的数据的大小Q选择最适合数据大小的slabQ图2Q? memcached中保存着slab内空闲chunk的列表,Ҏ该列表选择chunkQ? 然后数据缓存于其中?/p>
? 选择存储记录的组的方?/p>
实际上,Slab Allocator也是有利也有弊。下面介l一下它的缺炏V?/p>
Slab Allocator解决了当初的内存片问题Q但新的机制也给memcached带来了新的问题?/p>
q个问题是Q由于分配的是特定长度的内存Q因此无法有效利用分配的内存? 例如Q将100字节的数据缓存到128字节的chunk中,剩余?8字节浪费了Q图3Q?/p>
? chunkI间的?/p>
对于该问题目前还没有完美的解x案,但在文档中记载了比较有效的解x案?/p>
The most efficient way to reduce the waste is to use a list of size classes that closely matches (if that's at all possible) common sizes of objects that the clients of this particular installation of memcached are likely to store.
是_如果预先知道客户端发送的数据的公用大,或者仅~存大小相同的数据的情况下, 只要使用适合数据大小的组的列表,可以减浪贏V?/p>
但是很遗憾,现在q不能进行Q何调优,只能期待以后的版本了? 但是Q我们可以调节slab class的大的差别? 接下来说明growth factor选项?/p>
memcached在启动时指定 Growth Factor因子Q通过-f选项Q, 可以在某种E度上控制slab之间的差异。默认gؓ1.25? 但是Q在该选项出现之前Q这个因子曾l固定ؓ2Q称?#8220;powers of 2”{略?/p>
让我们用以前的设|,以verbose模式启动memcached试试看:
$ memcached -f 2 -vv
下面是启动后的verbose输出Q?/p>
slab class 1: chunk size 128 perslab 8192
slab class 2: chunk size 256 perslab 4096
slab class 3: chunk size 512 perslab 2048
slab class 4: chunk size 1024 perslab 1024
slab class 5: chunk size 2048 perslab 512
slab class 6: chunk size 4096 perslab 256
slab class 7: chunk size 8192 perslab 128
slab class 8: chunk size 16384 perslab 64
slab class 9: chunk size 32768 perslab 32
slab class 10: chunk size 65536 perslab 16
slab class 11: chunk size 131072 perslab 8
slab class 12: chunk size 262144 perslab 4
slab class 13: chunk size 524288 perslab 2
可见Q从128字节的组开始,l的大小依次增大为原来的2倍? q样讄的问题是Qslab之间的差别比较大Q有些情况下q当浪费内存? 因此Qؓ量减少内存费Q两q前q加了growth factorq个选项?/p>
来看看现在的默认讄Qf=1.25Q时的输出(幅所限,q里只写到第10l)Q?/p>
slab class 1: chunk size 88 perslab 11915
slab class 2: chunk size 112 perslab 9362
slab class 3: chunk size 144 perslab 7281
slab class 4: chunk size 184 perslab 5698
slab class 5: chunk size 232 perslab 4519
slab class 6: chunk size 296 perslab 3542
slab class 7: chunk size 376 perslab 2788
slab class 8: chunk size 472 perslab 2221
slab class 9: chunk size 592 perslab 1771
slab class 10: chunk size 744 perslab 1409
可见Q组间差距比因子?时小得多Q更适合~存几百字节的记录? 从上面的输出l果来看Q可能会觉得有些计算误差Q? q些误差是ؓ了保持字节数的对齐而故意设|的?/p>
memcached引入产品Q或是直接用默认D行部|时Q? 最好是重新计算一下数据的预期q_长度Q调整growth factorQ? 以获得最恰当的设|。内存是珍贵的资源,费太可惜了?/p>
接下来介l一下如何用memcached的stats命o查看slabs的利用率{各U各L信息?/p>
memcached有个名ؓstats的命令,使用它可以获得各U各L信息? 执行命o的方法很多,用telnet最为简单:
$ telnet L?端口?/pre>q接到memcached之后Q输入stats再按回RQ即可获得包括资源利用率在内的各U信息? 此外Q输?stats slabs"?stats items"q可以获得关于缓存记录的信息? l束E序误入quit?/p>
q些命o的详l信息可以参考memcached软g包内的protocol.txt文档?/p>
$ telnet localhost 11211
Trying ::1...
Connected to localhost.
Escape character is '^]'.
stats
STAT pid 481
STAT uptime 16574
STAT time 1213687612
STAT version 1.2.5
STAT pointer_size 32
STAT rusage_user 0.102297
STAT rusage_system 0.214317
STAT curr_items 0
STAT total_items 0
STAT bytes 0
STAT curr_connections 6
STAT total_connections 8
STAT connection_structures 7
STAT cmd_get 0
STAT cmd_set 0
STAT get_hits 0
STAT get_misses 0
STAT evictions 0
STAT bytes_read 20
STAT bytes_written 465
STAT limit_maxbytes 67108864
STAT threads 4
END
quit另外Q如果安装了libmemcachedq个面向C/C++语言的客L库,׃安装 memstat q个命o? 使用Ҏ很简单,可以用更的步骤获得与telnet相同的信息,q能一ơ性从多台服务器获得信息?/p>
$ memstat --servers=server1,server2,server3,...libmemcached可以从下面的地址获得Q?/p>
使用memcached的创造着Brad写的名ؓmemcached-tool的Perl脚本Q可以方便地获得slab的用情? Q它memcached的返回值整理成Ҏ阅读的格式)。可以从下面的地址获得脚本Q?/p>
使用Ҏ也极其简单:
$ memcached-tool L?端口 选项
查看slabs使用状况时无需指定选项Q因此用下面的命令即可:
$ memcached-tool L?端口
获得的信息如下所C:
# Item_Size Max_age 1MB_pages Count Full?
1 104 B 1394292 s 1215 12249628 yes
2 136 B 1456795 s 52 400919 yes
3 176 B 1339587 s 33 196567 yes
4 224 B 1360926 s 109 510221 yes
5 280 B 1570071 s 49 183452 yes
6 352 B 1592051 s 77 229197 yes
7 440 B 1517732 s 66 157183 yes
8 552 B 1460821 s 62 117697 yes
9 696 B 1521917 s 143 215308 yes
10 872 B 1695035 s 205 246162 yes
11 1.1 kB 1681650 s 233 221968 yes
12 1.3 kB 1603363 s 241 183621 yes
13 1.7 kB 1634218 s 94 57197 yes
14 2.1 kB 1695038 s 75 36488 yes
15 2.6 kB 1747075 s 65 25203 yes
16 3.3 kB 1760661 s 78 24167 yes
各列的含义ؓQ?/p>
?/td> | 含义 |
# | slab class~号 |
Item_Size | Chunk大小 |
Max_age | LRU内最旧的记录的生存时?/td> |
1MB_pages | 分配lSlab的页?/td> |
Count | Slab内的记录?/td> |
Full? | Slab内是否含有空闲chunk |
从这个脚本获得的信息对于调优非常方便Q强烈推荐用?/p>
本次单说明了memcached的缓存机制和调优Ҏ? 希望读者能理解memcached的内存管理原理及其优~点?/p>
下次l说明LRU和Expire{原理,以及memcached的最新发展方向—? 可扩充体p(pluggable architecherQ)?/p>
译一技术评论社的文章,是讲memcached的连载?a >fcicq同学说这个东西很有用Q希望大家喜Ƣ?/p>
发表日:2008/7/2
作者:镉K雅广(Masahiro Nagano)
原文链接Q?a >http://gihyo.jp/dev/feature/01/memcached/0001
我是mixi株式会社开发部pȝq营l的镉K? 日常负责E序的运营。从今天开始,分几次针对最q在Web应用的可扩展性领? 的热门话题memcachedQ与我公司开发部研究开发组的前坂一P 说明其内部结构和使用?/p>
memcached 是以LiveJournal 旗下Danga Interactive 公司?a >Brad Fitzpatric 为首开发的一ƾY件。现在已成ؓ mixi? hatena? Facebook? Vox、LiveJournal{众多服务中 提高Web应用扩展性的重要因素?/p>
许多Web应用都将数据保存到RDBMS中,应用服务器从中读取数据ƈ在浏览器中显C? 但随着数据量的增大、访问的集中Q就会出现RDBMS的负担加重、数据库响应恶化? |站昄延迟{重大媄响?/p>
q时pmemcached大显w手了。memcached是高性能的分布式内存~存服务器? 一般的使用目的是,通过~存数据库查询结果,减少数据库访问次敎ͼ以提高动态Web应用的速度? 提高可扩展性?/p>
? 一般情况下memcached的用?/p>
memcached作ؓ高速运行的分布式缓存服务器Q具有以下的特点?/p>
memcached的服务器客户端通信q不使用复杂的XML{格式, 而用简单的Z文本行的协议。因此,通过telnet 也能在memcached上保存数据、取得数据。下面是例子?/p>
$ telnet localhost 11211
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
set foo 0 0 3 Q保存命令)
bar Q数据)
STORED Q结果)
get foo Q取得命令)
VALUE foo 0 3 Q数据)
bar Q数据)
协议文档位于memcached的源代码内,也可以参考以下的URL?/p>
libevent是个E序库,它将Linux的epoll、BSDcL作系l的kqueue{事件处理功? 装成统一的接口。即使对服务器的q接数增加,也能发挥O(1)的性能? memcached使用q个libevent库,因此能在Linux、BSD、Solaris{操作系l上发挥光性能? 关于事g处理q里׃再详l介l,可以参考Dan Kegel的The C10K Problem?/p>
Z提高性能Qmemcached中保存的数据都存储在memcached内置的内存存储空间中? ׃数据仅存在于内存中,因此重启memcached、重启操作系l会D全部数据消失? 另外Q内容容量达到指定g后,基于LRU(Least Recently Used)法自动删除不用的~存? memcached本n是ؓ~存而设计的服务器,因此q没有过多考虑数据的永久性问题? 关于内存存储的详l信息,本连载的W二讲以后前坂会q行介绍Q请届时参考?/p>
memcached管?#8220;分布?#8221;~存服务器,但服务器端ƈ没有分布式功能? 各个memcached不会互相通信以共享信息。那么,怎样q行分布式呢Q? q完全取决于客户端的实现。本q蝲也将介绍memcached的分布式?/p>
? memcached的分布式
接下来简单介l一下memcached的用方法?/p>
memcached的安装比较简单,q里E加说明?/p>
memcached支持许多q_?/p>
另外也能安装在Windows上。这里用Fedora Core 8q行说明?/p>
q行memcached需要本文开头介l的libevent库。Fedora 8中有现成的rpm包, 通过yum命o安装卛_?/p>
$ sudo yum install libevent libevent-devel
memcached的源代码可以从memcached|站上下载。本文执W时的最新版本ؓ1.2.5? Fedora 8虽然也包含了memcached的rpmQ但版本比较老。因为源代码安装q不困难Q? q里׃使用rpm了?/p>
memcached安装与一般应用程序相同,configure、make、make installp了?/p>
$ wget http://www.danga.com/memcached/dist/memcached-1.2.5.tar.gz
$ tar zxf memcached-1.2.5.tar.gz
$ cd memcached-1.2.5
$ ./configure
$ make
$ sudo make install
默认情况下memcached安装?usr/local/bin下?/p>
从终端输入以下命令,启动memcached?/p>
$ /usr/local/bin/memcached -p 11211 -m 64m -vv
slab class 1: chunk size 88 perslab 11915
slab class 2: chunk size 112 perslab 9362
slab class 3: chunk size 144 perslab 7281
中间省略
slab class 38: chunk size 391224 perslab 2
slab class 39: chunk size 489032 perslab 2
<23 server listening
<24 send buffer was 110592, now 268435456
<24 server listening (udp)
<24 server listening (udp)
<24 server listening (udp)
<24 server listening (udp)
q里昄了调试信息。这样就在前台启动了memcachedQ监听TCP端口11211 最大内存用量?4M。调试信息的内容大部分是关于存储的信息, 下次q蝲时具体说明?/p>
作ؓdaemon后台启动Ӟ只需
$ /usr/local/bin/memcached -p 11211 -m 64m -d
q里使用的memcached启动选项的内容如下?/p>
选项 | 说明 |
-p | 使用的TCP端口。默认ؓ11211 |
-m | 最大内存大。默认ؓ64M |
-vv | 用very vrebose模式启动Q调试信息和错误输出到控制台 |
-d | 作ؓdaemon在后台启?/td> |
上面四个是常用的启动选项Q其他还有很多,通过
$ /usr/local/bin/memcached -h
命o可以昄。许多选项可以改变memcached的各U行为, 推荐M诅R?/p>
许多语言都实Cq接memcached的客LQ其中以Perl、PHPZ? 仅仅memcached|站上列出的语言有
{等?/p>
q里介绍通过mixi正在使用的Perl库链接memcached的方法?/p>
Perl的memcached客户端有
{几个CPAN模块。这里介l的Cache::Memcached是memcached的作者Brad Fitzpatric的作品, 应该是memcached的客L中应用最为广泛的模块了?/p>
下面的源代码为通过Cache::Memcachedq接刚才启动的memcached的例子?/p>
在这里,为Cache::Memcached指定了memcached服务器的IP地址和一个选项Q以生成实例? Cache::Memcached常用的选项如下所C?/p>
选项 | 说明 |
servers | 用数l指定memcached服务器和端口 |
compress_threshold | 数据压羃时用的?/td> |
namespace | 指定d到键的前~ |
另外QCache::Memcached通过Storable模块可以Perl的复杂数据序列化之后再保存, 因此散列、数l、对象等都可以直接保存到memcached中?/p>
向memcached保存数据的方法有
它们的用方法都相同Q?/p>
my $add = $memcached->add( '?, '?, '期限' );
my $replace = $memcached->replace( '?, '?, '期限' );
my $set = $memcached->set( '?, '?, '期限' );
向memcached保存数据时可以指定期?U?。不指定期限Ӟmemcached按照LRU法保存数据? q三个方法的区别如下Q?/p>
选项 | 说明 |
add | 仅当存储I间中不存在键相同的数据时才保存 |
replace | 仅当存储I间中存在键相同的数据时才保?/td> |
set | 与add和replace不同Q无Z旉保存 |
获取数据可以使用get和get_multiҎ?/p>
my $val = $memcached->get('?);
my $val = $memcached->get_multi('?', '?', '?', '?', '?');
一ơ取得多条数据时使用get_multi。get_multi可以非同步地同时取得多个键| 光度要比循环调用get快数十倍?/p>
删除数据使用deleteҎQ不q它有个独特的功能?/p>
$memcached->delete('?, 'd旉(U?');
删除W一个参数指定的键的数据。第二个参数指定一个时间|可以止使用同样的键保存新数据? 此功能可以用于防止缓存数据的不完整。但是要注意Q?strong>set函数忽视该阻塞,照常保存数据
可以memcached上特定的键g数器使用?/p>
my $ret = $memcached->incr('?);
$memcached->add('?, 0) unless defined $ret;
增一和减一是原子操作,但未讄初始值时Q不会自动赋?。因此, 应当q行错误查,必要时加入初始化操作。而且Q服务器端也不会? 过2<sup>32</sup>时的行ؓq行查?/p>
q次单介l了memcachedQ以及它的安装方法、Perl客户端Cache::Memcached的用法? 只要知道Qmemcached的用方法十分简单就_了?/p>
下次由前坂来说明memcached的内部结构。了解memcached的内部构造, p知道如何使用memcached才能使Web应用的速度更上一层楼? Ƣ迎l箋阅读下一章?/p>