显示标签为“memcached”的博文。显示所有博文
显示标签为“memcached”的博文。显示所有博文

2013年2月21日星期四

分布式缓存系统 Memcached 入门

© kekehu / 技术资源 / 2010.11.25 / 11:32 / 4282PV
维基百科上对 Memcached 的介绍是一个分布式的缓存系统, 但是 Memcachd 到底是什么意思,有什么作用呢?缓存一般用来保存一些经常被存取的数据和资源(例如:浏览器会将访问过的网页会话缓存起来),因为通过缓存来存取数据要比从磁盘存取同样的数据要快得多。所以 顾名思义,意味着 “内存缓存”,所有缓存的内容都在服务器的内存中。内存中的这些缓存数据可以通过 API 的方式被存取。数据是以 key/value 的配对方式存在的,就像一个很大的 Hash 表。

分布式是 的主要特性,所以你可以在多台服务器上来安装 来组建一个更大的缓存服务器。这样一来, 可以帮助我们使数据库的压力降到最低, 从而我们可以构建出更快的、更具扩展性的 WEB 应用。图一展示了 Memcache 如何与数据库端协同工作的情况。



图一:Memcache 如何和数据库协同工作

Memcache 如何工作?


图一展示的流程,相信有开发过数据库应用的同学都不会陌生。我们来一步步的说明图中发生了什么事情:
  1. 检查用户请求的数据是缓存中是否有存在,如果有存在的话,只需要直接把请求的数据返回,这时候跟数据库就完全扯不上关系了。
  2. 如果请求的数据在缓存中找不到,这时候再去查询数据库。返回请求数据的同时,把数据存储到缓存中一份。
  3. 保持缓存的“新鲜性”,每当数据发生变化的时候(比如,数据有被修改,或被删除的情况下),要同步的更新缓存信息,确保用户不会在缓存取到旧的数据。

显而易见, 在高并发的数据查询和海量数据输出的情况下,可以起到很大的作用。因为访问 中的内存数据,要比数据库的磁盘数据快的多。

如何安装 Memcache?

如果你想在自己的服务器上尝试使用 ,第一步就是要在你的服务器上安装 的相关组件。好在 在很多服务器的发行版软件上都已经被预安装了。你可以通过在 Shell 下执行下面的命令,来检查你的服务器上有没有被预安装了
memcached -h
如果 有被安装过,上面的命令会输出已经安装的版本号信息及一些帮助信息,否则则会返回一个错误。
下面以 CentOs 发行版为例,简单介绍一下如何安装
yum install memcached
上面的命令会在线搜索并安装最新的 包。

Memcache 在什么情况下被使用,什么情况下不要使用?


你在何时应该使用 Memcache,又要在何时避免使用它?现在你已经知道了,Memcahced 是被设计为减轻数据库端压力的。但是你最好能制定一个良好的策略,来想办法让 来尽可能的缓存那些最影响性能的查询。你可以试着为应用中的所有查询做一些执行时间日志,可以帮助你来分析哪些内容是要重点被缓存的。
现在假设你正在运营一个电子商务网站。 你可以在 中缓存产品的简介、运送信息,或者其它一些需要复杂查询的数据,等等。当一个产品页被加载的时候,上面提到的数据将会跳过数据库查询,直接从缓存中取得。缓存可以大大的改变你的网站整体性能表现,你只需要记得在后台更新产品的时候,把这些缓存一并更新就行了。
还有一些情况下,缓存数据并不是一个好主意,比如在一个数据被频繁更新的时候,每一次数据的更新,我们都需要去同时更新缓存,缓存的命中率不高,会导致一些额外的性能牺牲。这种情况下,或许直接查数据库会更好一些。

的安全性

如果你了解了 的工作流程, 你可能已经注意到了,在访问缓存的过程中,没有任何权限控制的相关流程。如果你的数据不是非常重要的,你大可不必担心这方面的安全问题。如果你需要的话,以下几点可以协助你更完全的使用它:
  1. 使用唯一的 Key:因为在 中的数据是以一个大的数组形式存在的,所以你应该使用唯一的 key。访问你的数据的唯一办法就是通过你保存数据时的 key,除此之外再没有其它可查询的办法。
  2. 保证你的 器安全: 因为 本身并没有身份验证机制,所以对 的服务器查询,都应该通过防火墙进行。你可以在防火墙上设定规则,哪些服务器是允许被访问的,哪些是不允许被访问的。
  3. 加密你的数据: 你可以将数据和 Key 通过加密的方式保存在 中。 这需要花费一些额外的 CPU 时间,但是为了你的数据安全,在情况允许的情况下,这个方法值得你去尝试。

代码实例

让我们来看一个实际的 PHP 例子。下面的代码展示了如何从缓存中取得数据,如果数据不存在,则自动从数据库中查询需要的数据,并将查询到的数据保存到缓存中的过程。
要在你的网站使用上面的代码,请先确认你有安装 Memcached 的 PHP 扩展。你可以通过 PECL 来安装对应的开发包。
class MyCache
{
  private $cache;
  function  __construct()
  {
    $this->cache = new Memcache();
    // you can replace localhost by Memcached server IP addr and port no.
    $this->cache->connect('localhost', 10987);
  }
 
  function get_data($key)
  {
    $data = $this->cache->get($key);
    if($data != null)
      return $data;
    else
    {
      if($this->cache->getResultCode() == Memcached::RES_NOTFOUND)
      {
        //do the databse query here and fetch data
        $this->cache->set($key,$data_returned_from_database);
      }
      else
      {
        error_log('No data for key '.$key);
      }
    }
  }
}
 
$cache = MyCache();
$cache->get_data('foo');

总结

是一个强大的工具,帮忙你建立像 Wikipedia、Flickr、Digg 这样的大型 WEB 应用。只要通过 就可以轻松提高你的站点性能,你还等什么?
翻译:avenge
原文链接:http://www.developer.com/features/article.php/52691_3901666_1/Getting-Started-with-Memcached-Distributed-Memory-Caching.htm

2013年2月17日星期日

使用libmemcached提速memcached的操作



memcachedCacheRailsRubyGoogle
libmemcached是一个基于C/C++实现的memcached client library,memcached gem给这个library提供了ruby封装,根据原作者的性能评测,它比目前常用的memcache-client gem最多要快150倍。

因为对memcache的操作在rails处理整个http请求中所占时间比例并不多,而且JavaEye网站大部分是做cache读取操作,于是做了2个试验测试一下2者对于提升整个网站的性能到底有多少帮助:
1. 测试访问JavaEye网站的首页,在这个请求中只有一个缓存读取操作,使用ab简单地跑单次请求10000次:
使用memcache-client,平均完成每个请求是9.247 ms
使用memcached,平均完成每个请求是8.982 ms

对于整体性能提升在3%左右

2. 测试访问某个论坛版面的页面,整个请求有超过60次的缓存读取操作,使用ab简单跑单次请求1000次:
使用memcache-client,平均完成每个请求是95.872 ms
使用memcached,平均完成每个请求是91.591 ms

对于整体性能提升在5%左右

从试验可以看出,对于整体性能还是有一定提高的。JavaEye用的cache插件是cache_fu,它只支持memcache-client,不过通过简单的修改就可以支持这个新gem,我提交了一个补丁,有兴趣的话可以从这里下载到补丁。

--分割线--
cache_fu的作者已经将这个补丁添加到代码树,可以从github checkout:  http://github.com/defunkt/cache_fu/tree/master

libmemcached使用(c 客户端连接 memcached) 2011-07-14 15:07:13



libmemcached 下载地址。https://launchpad.net/libmemcached/


//g++ -o testmemcached testmemcached.cpp -lmemcached


#include <iostream>
#include <string>
#include <libmemcached/memcached.h>

using namespace std;

int main(int argc,char *argv[])
{
   //connect server

   memcached_st *memc;
   memcached_return rc;
   memcached_server_st *server;
   time_t expiration;
   uint32_t flags;

   memc = memcached_create(NULL);
   server = memcached_server_list_append(NULL,"localhost",11211,&rc);
   rc=memcached_server_push(memc,server);
   memcached_server_list_free(server);

   string key = "key";
   string value = "value";
   size_t value_length = value.length();
   size_t key_length = key.length();


   //Save data

   rc=memcached_set(memc,key.c_str(),key.length(),value.c_str(),value.length(),expiration,flags);
   if(rc==MEMCACHED_SUCCESS)
   {
       cout<<"Save data:"<<value<<" sucessful!"<<endl;
   }

   //Get data

   char* result = memcached_get(memc,key.c_str(),key_length,&value_length,&flags,&rc);
   if(rc == MEMCACHED_SUCCESS)
   {
       cout<<"Get value:"<<result<<" sucessful!"<<endl;
   }

   //Delete data

   rc=memcached_delete(memc,key.c_str(),key_length,expiration);
   if(rc==MEMCACHED_SUCCESS)
   {
       cout<<"Delete key:"<<key<<" sucessful!"<<endl;
   }

   //free

   memcached_free(memc);
   return 0;
}



在下载客户端 libmemcached-0.50/tests 下有测试列子,也可参考。比如cpp_example.cc

memcached简单的使用教程


这是工程应用性质的文章:memcached是数据快速存取的工具,wikipedia和facebook就用了它提高速度。具体情况可以wiki.

c/c++里面使用memcached本来是很简单的事情,但就是没有人说,非要我去读libmemcache的实例代码才行,manpage也没有说清楚(但还不得不看)。如果要使用memcached,步骤如下:

1 安装memcached
  你可以去官网 上下载,也可以sudo apt-get install memcached
2 测试你刚才的安装,
  比如运行 memcached -d -m 64 -l 127.0.0.1 -p 12300
  -d表示后台, -m 64表示使用64MB内存,-l 127.0.0.1 -p 12300 表示监听127.0.0.1:12300端口
  没有任何消息就是运行成功
3 安装libmemcached
  这个就不要apt了,因为没有精确的libmemcached包,乖乖去官网 下载吧。这个东西还需要libevent,这个没法apt,libevent安装的时候最好装到/usr/lib里面,不然libmemcached还不能运行。
4 测试libmemcached
  找一个文件比如test,然后运行memcp test --servers=127.0.0.1:12300
  这样就把test拷贝到memcached管理的内存里面了。
  memcat test --servers=127.0.0.1:12300
  看看是不是刚才的那个文件。

该装的全装了,我们可以改代码了。
(以下引自:wikipedia)

将纯粹使用数据库查询的程式码加上memcached支援是很简单的,假设这是原来的程式码:

function get_foo (int userid) {

   result = db_select("SELECT * FROM users WHERE userid = ?", userid);

   return result;

}

加上memcached的快取机制后:

function get_foo (int userid) {

    result = memcached_fetch("userrow:" + userid);

    if (!result) {

        result = db_select("SELECT * FROM users WHERE userid = ?", userid);

        memcached_add("userrow:" + userid,  result);

    }

    return result;

}

(wikipedia 引述完毕)

但我们需要初始化,而且需要c/c++的表述形式:
首先修改makefile,在LIBS里面加上-lmemcached,比如原来 gcc test.c,现在 gcc test.c -lmemcached。这个库就是libmemcached提供的。
然后添加#include<libmemcached/memcached.h>,这个文件也是libmemcached提供的。
主函数里面需要添加:
    memcached_st *memc;
    uint32_t  flags;
    memcached_return rc;
    memcached_server_st *servers;
    memc= memcached_create(NULL);

    servers= memcached_servers_parse("127.0.0.1:12300");
    memcached_server_push(memc, servers);
    memcached_server_list_free(servers);
    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 0);
   
这就是初始化的全部代码,可以设置很多东西,不过我现在只要一个服务器,就看一句话:
    servers= memcached_servers_parse("127.0.0.1:12300");
这就是指明要连接到位于127.0.0.1监听12300端口的memcached程序. 其他都不管。

我最后用一段修改后的代码介绍两个函数,memcached_get和memcached_set,都可以man出来。

        char * result_str; /*这个就是查询的结果*/
        std::string query="要查询的数据名";

        result_str= memcached_get(memc, query.c_str(), strlen(query.c_str()),
                &result_str_length, &flags, &rc);

        if (rc == MEMCACHED_SUCCESS)
        {
            printf("%s",result_str);
            free(result_str); /*一定要free掉 memcached传回的数据*/

            continue;
        }
        else if (rc == MEMCACHED_NOTFOUND)
        {
            /*读取数据*/
            ...
            rc= memcached_set(memc, query.c_str(), strlen(query.c_str()),
                    str_result.c_str(), strlen(str_result.c_str()),
                    0, 0);
        }

这东西设计得还是很好用的,libmemcached好像是面向对象c语言风格的东西,好不好用就让我们拭目以待吧。
/////////////////////////////////////////////////////////////////////////////////
完整的例子:
#include <stdio.h>
#include <stdlib.h>
#include <libmemcached/memcached.h>
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
 memcached_server_st *servers = memcached_servers_parse("127.0.0.1:22222");
 memcached_st *memc = memcached_create(NULL);
 memcached_server_push(memc, servers);
 memcached_server_list_free(servers);
 memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 0);
 string strKey = "1";
 string strValue = "hello.world";
 memcached_return rc = memcached_set(memc, strKey.c_str(), strlen(strKey.c_str()), strValue.data(), strValue.size(), 0, 0);
 if (rc == MEMCACHED_SUCCESS)
 {
  printf("memcached_set ok! \n");
  size_t ValueLength = 0;
  uint32_t flags;
  char *pValue = memcached_get(memc, strKey.c_str(), strlen(strKey.c_str()), &ValueLength, &flags, &rc);
  if (rc == MEMCACHED_SUCCESS)
  {
   printf("memcached_get key=%s value=%s \n", strKey.c_str(), pValue);
   free(pValue);
  }
 }
 memcached_free(memc);
 return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////
memcached 命令
memcached 命令



comments 类型



1. storage commands: set add replace

2. retrieval commands: get

3. other commands: incr delete



error strings

1. "ERROR\r\n"

客户端发送了一个不存在的command



2. "CLIENT_ERROR <error>\r\n"

客户端的错误:客户端发送的数据或者格式方面有问题。 <error>表示具体错误的原因。



3. "SERVER_ERROR <error>\r\n"

服务器端的错误:服务器一系列的错误阻止了命令的执行。<error>表示具体错误的原因。当发生此错误时。服务器发送完了"SERVER_ERROR <error>\r\n"之后将会关闭connection。(这是唯一的关闭connection的情况)



descriptions of individual commands



1. storage commands

首先客户端向服务器按照如下格式发送命令行:

<command name> <key> <flags> <exptime> <bytes>\r\n



a) <command name> 可以是"set", "add", "replace"。

"set"表示按照相应的<key>存储该数据。

"add"表示按照相应的<key>添加该数据,但是如果该<key>已经存在则会操作失败。

"replace"表示按照相应的<key>替换数据,但是如果该<key>不存在则操作失败



b) <key> 客户端需要保存数据的key。



c) <flags> 是一个16位的无符号的整数(以十进制的方式表示)。该标志将和需要存储的数据一起存储,并在客户端get数据时返回。客户可以将此标志用做特殊用途,此标志对服务器来说是不透明的。



d) <exptime> 过期的时间。如果该数值为0表示存储的数据永远不过时(但是,该数据有可能被其他项所替换掉。因为服务器采用了LRU(最近最久没有使用)的算法替换)。如果非0(unix时间或者距离此时的秒数),当过期后,服务器可以保证用户得不到该数据(以服务器时间为标准)。



e) <bytes> 需要存储的字节数(不包含最后的"\r\n"),当用户希望存储空数据时,<bytes>可以为0



f) 最后客户端需要加上"\r\n"作为"命令头"的结束标志。



<data block>\r\n

紧接着"命令头"结束之后就要发送数据块(即希望存储的数据内容),最后加上"\r\n"作为此次通讯的结束。



reply

当以上数据发送结束之后,服务器将返回一个应答。可能有如下的情况:



a) "STORED\r\n"

表示存储成功



b) "NOT_STORED\r\n"

表示存储失败,但是该失败不是由于错误。通常这是由于"add"或者"replace"命令本身的要求所引起的,或者该项在删除队列之中(见delete命令)。



2 retrieval command

获取数据的格式:



get <key>*\r\n



a) <key>* 表示一个或者多个key(以空格分开)



b) "\r\n" 命令头的结束



reply

服务器端将返回0个或者多个的数据项。每个数据项都是由一个文本行和一个数据块组成。当所有的数据项都接收完毕将收到"END\r\n"



每一项的数据结构:

VALUE <key> <flags> <bytes>\r\n

<data block>\r\n



a) <key> 希望得到存储数据的key



b) <falg> 发送set命令时设置的标志项



c) <bytes> 发送数据块的长度(不包含"\r\n")



d) "\r\n" 文本行的结束标志



e) <data block> 希望接收的数据项。



f) "\r\n" 接收一个数据项的结束标志。



如果有些key出现在get命令行中但是没有返回相应的数据,这意味着服务器中不存在这些项,这些项过时了,或者被删除了。



3. delete

delete 命令格式:

delete <key> <time>\r\n



a) <key> 需要被删除数据的key



b) <time> 客户端希望服务器将该数据删除的时间(unix时间或者从现在开始的秒数)



c) "\r\n" 命令头的结束



reply



a) "DELETED\r\n" 删除成功



b) "NOT_FOUND\r\n" 需要删除的key不存在



ps:"flush_all" command 可以所有项都无效。



4. increment/decrement



command "incr" "decr" 是用来改变数据项数值的命令。设置数据项的数据被认为是一个10进制的无符号的整数。如果当前设置的值不能够被转换则认为是0.如果该数据项的key不存在,则执行命令失败!



命令格式:



incr <key> <value>\r\n

or

decr <key> <value>\r\n



a) <key> 数据项的key



b) <value> 用户希望增加/减少的数据的数值.该数值是一个32位十进制的无符号整形变量。



c) "\r\n" 命令行结束标志



reply



a) "NOT_FOUND\r\n" 没有找到需要操作的项。



b) "<value>\r\n" <value>数据项有效期的最新剩余时间。



注意:

a) 如果一个数据项的有效期被设置为0,这时使用decr命令是无法减少数据。



b) 如果要执行 incr key -1 的操作不会有什么问题,结果和你希望的一样。但是,执行decr -1时的结果一定会让你觉得很意外,因为它的结果无论key的数据是什么结果的都是0.原因是:在这两个命令的执行过程中都是吧-1当做一个无符号的整形处理的。



c) 执行decr命令时数据的长度不会随之而减小,而是在返回数据的后面填补空格。但是执行incr命令越界后会自动的增加数据的位数。





5. 其他命令



"stats": 用来查询服务器提供的内部数据。



stats <args>\r\n

查询特定的数据



reply



STAT <name> <value>\r\n

...

END\r\n



"quit"

"quit\r\n": 退出程序


///////////////////////////////////////////////////////////////////////////////////////////////////


对于 Memcached 缓存系统的基本介绍、安装以及应用 之前有一编文章说过,下面主要是对使用Memcached系统的基本命令以及协议作个简单的分析,个人学习的笔记,呵呵。还希望能给需要的筒子一点参考:

一、Memcache面向对象的常用接口包括:
Memcache::connect -- 打开一个到Memcache的连接
Memcache::pconnect -- 打开一个到Memcache的长连接
Memcache::close -- 关闭一个Memcache的连接
Memcache::set -- 保存数据到Memcache服务器上
Memcache::get -- 提取一个保存在Memcache服务器上的数据
Memcache::replace -- 替换一个已经存在Memcache服务器上的项目
Memcache::delete -- 从Memcache服务器上删除一个保存的项目
Memcache::flush -- 刷新所有Memcache服务器上保存的项目(类似于删除所有的保存的项目)
Memcache::getStats -- 获取当前Memcache服务器运行的状态

For More: http://cn.php.net/memcache

二、查看系统的运行状态:


pid               Process id of this server process (memcache服务器的进程ID)
uptime            Number of seconds this server has been running (服务器已经运行的秒数)
time              Current UNIX time according to the server (服务器当前的UNIX时间)
version           Version string of this server (memcache版本)
pointer_size      Current system pointer 当前操作系统的指针大小(32位系统一般是32bit)
rusage_user       Accumulated user time for this process (该进程累计的用户时间(秒:微妙))
rusage_system     Accumulated system time for this process (该进程累计的系统时间(秒:微妙))
curr_items        Current number of items stored by the server (服务器当前存储的内容数量)
total_items       Total number of items stored by this server ever since it started (服务器启动以来存储过的内容总数)
bytes             Current number of bytes used by this server to store items (服务器当前存储内容所占用的字节数)
curr_connections  Number of open connections (当前打开着的连接数量)
total_connections Total number of connections opened since the server started running (服务器运行以来接受的连接总数)
connection_structures Number of connection structures allocated by the server (服务器分配的连接结构的数量)
cmd_get             Cumulative number of retrieval requests (get命令(获取)总请求次数)
cmd_set             Cumulative number of storage requests (set命令(保存)总请求次数)
get_hits            Number of keys that have been requested and found present (请求成功的总次数)
get_misses          Number of items that have been requested and not found (请求失败的总次数)
threads             Current number of thread (当前线程数)
bytes_read          Total number of bytes read by this server from network (服务器从网络读取到的总字节数)
bytes_written       Total number of bytes sent by this server to network (服务器向网络发送的总字节数)
limit_maxbytes      Number of bytes this server is allowed to use for storage. (服务器在存储时被允许使用的字节总数)
evictions           Number of valid items removed from cache to free memory for new items (为获取空闲内存而删除的items数(分配给memcache的空间用满后需要删除旧的items来得到空间分配给新的items))

其中,最关注最多的几个参数:
uptime:是memcached运行的秒数。
cmd_get:是查询缓存的次数。
cmd_get/uptime 结果是平均每秒请求缓存的次数——结果值越大,说明Memcached的利用率越高,站点的访问量大,如果太低,用文件系统缓存就可以了,根本不会体现出使用memcached的强大性能。
cmd_set:是设置key=>value的次数。整个memcached是个大hash,用cmd_get没有找到的内容,就会调用一下cmd_set写进缓存里。
get_hits:是缓存命中的次数。所谓的命中率 = get_hits/cmd_get * 100%。
get_misses:是缓存未命中的次数。get_misses加上get_hits就等于cmd_get。
stats:显示服务器信息、统计数据等
stats reset:清空统计数据

stats slabs:显示各个slab的信息,包括chunk的大小、数目、使用情况等
stats items:显示各个slab中item的数目和存储时长(最后一次访问距离现在的秒数)
quit:退出

三、利用shell命令操作Memcached
1、数据存储(key为wan,value为123)

2、数据取回

3、替换数据(将以wan为key存储的值替换为122)

4、数值增加 1

5、数值减少 2

6、数据删除

7、查看Memcached当时状态
printf "stats\r\n" | nc 127.0.0.1 11211
8、查看Memcached实时状态

watch "printf 'stats\r\n' | nc 127.0.0.1 11211"



Memcached protocol 中英文档可以参考:

http://blog.s135.com/book/memcached/

四. 查看slabs的使用状况
使用memcached的创造着Brad写的名为 memcached-tool 的Perl脚本,可以方便地获得slab的使用情况(它将memcached的返回值整理成容易阅读的格式)。可以从下面的地址获得脚本:
http://code.sixapart.com/svn/memcached/trunk/server/scripts/memcached-tool
[root@localhost html]# vim memcached-tool
[root@localhost html]# chmod +x memcached-tool
[root@localhost html]# ./memcached-tool 127.0.0.1:11211
  #  Item_Size   Max_age  1MB_pages Count   Full?
  1      80 B        0 s               1           0      no
  2     104 B       12175 s         1           1      no
  3     176 B    1339587 s       33       196567  yes

各列的含义:
#: slab class编号
Item_Size: Chunk大小
Max_age: LRU内最旧的记录的生存时间
1MB_pages: 分配给Slab的页数
Count: Slab内的记录数
Full?: Slab内是否含有空闲chunk

五. 也可以图形化监控 Memcached 的运行状态
http://livebookmark.net/journal/2008/05/21/memcachephp-stats-like-apcphp/
是一个PHP源文件,只需要修改源码中的用户名、密码以及数组$MEMCACHE_SERVERS 就可以了。

我的apache php mysql libmemcached memcached 安装实践


参考http://www.hao32.com/webserver/313.html
/sbin/ldconfig 这个命令在安装了新的动态链接库后运行一下,避免依赖此链接库的程序找不到它。
安装apache
wget "http://apache.freelamp.com/httpd/httpd-2.2.15.tar.gz"
tar -xzf httpd-2.2.15.tar.gz
cd httpd-2.2.15
./configure --prefix=/home/zhaigy/apache_n --enable-so
make
make install
安装php
wget "http://cn.php.net/distributions/php-5.3.2.tar.gz"
tar -xzf php-5.3.2.tar.gz
cd php-5.3.2
./configure --prefix=/home/zhaigy/php_n --with-apxs2=/home/webadm/bin/apxs
make
make install
修改httpd.conf
user zhaigy
group zhaigy
LoadModule php4_module modules/libphp4.so (这一项在装完php后会自动添加)
AddType application/x-httpd-php .php (这一项手工添加)
chown -R zhaigy.zhaigy /home/zhaigy/apache_n
启动apache
cd /home/zhaigy/apache_n
./bin/apachectl start
测试
netstat -npl
浏览器打开首页测试
查看phpinfo信息 (可获知:Configuration File (php.ini) Path /home/zhaigy/php_n/lib )
给php添加mysql扩展
cd /home/zhaigy/php-5.3.2/ext/mysql
/home/zhaigy/php_n/bin/phpize
./configure --help
./configure --with-php-config=/home/zhaigy/php_n/bin/php-config --with-mysql="/home/zhaigy/mysql-5.1.22-rc-linux-x86_64-glibc23"
或者./configure --with-php-config=/home/zhaigy/php_n/bin/php-config --with-mysql="mysqlnd"
make
make install 显示 Installing shared extensions:     /home/zhaigy/php_n/lib/php/extensions/no-debug-non-zts-20090626/
cd /home/zhaigy/php_n/
mkdir modules
cp /home/zhaigy/php_n/lib/php/extensions/no-debug-non-zts-20090626/mysql.so ./modules
编写php.ini 参考 http://lamp.linux.gov.cn/PHP/php-5_2-ini.html
修改extension_dir = "/home/zhaigy/php_n/modules"
extension = mysql.so
chown -R zhaigy.zhaigy /home/zhaigy/php_n
重启apache
cd /home/zhaigy/apache_n
./bin/apachectl restart
netstat -npl|grep httpd
php安装源码中不包含的其它扩展,例如 memcached
################################
这个可以不安装
安装 memcached
wget "http://memcached.googlecode.com/files/memcached-1.4.5.tar.gz"
tar -xzvf memcached-1.4.5.tar.gz
cd memcached-1.4.5
./configure --prefix=/home/zhaigy/memcached_n --enable-64bit
make
make install
################################
需要先安装libmemcached
cd /home/zhaigy
wget "http://launchpad.net/libmemcached/1.0/0.42/+download/libmemcached-0.42.tar.gz"
tar -xzf libmemcached-0.42.tar.gz
cd libmemcached-0.42
./configure --prefix=/home/zhaigy/libmemcached_n --without-memcached
--非常的痛苦啊,编译安装在这里总是失败,从网上找的解决方法也不能用
痛苦的3小时
--
无意中使用了旧的版本,发现编译错误少了几个,嗯,找更旧的
cd /home/zhaigy
wget "http://launchpadlibrarian.net/33299675/libmemcached-0.28.tar.gz"
tar xzvf libmemcached-0.28.tar.gz
cd libmemcached-0.28
./configure --prefix=/home/zhaigy/libmemcached_n --without-memcached
make
make install
--这次比较顺利,估计是因为机器上的gcc版本低吧

cp /home/zhaigy/php_n
./bin/pecl -h
./bin/pecl download memcached
tar -xf memcached-1.0.2.tar
cd memcached-1.0.2
/home/zhaigy/php_n/bin/phpize
./configure --with-php-config=/home/zhaigy/php_n/bin/php-config --with-libmemcached-dir="/home/zhaigy/libmemcached_n"
make 这里也遇到编译错误
降低版本
/home/zhaigy/php_n/bin/pecl download memcached-1.0.0
tar -xvf memcached-1.0.0.tar
cd memcached-1.0.0
/home/zhaigy/php_n/bin/phpize
./configure --with-php-config=/home/zhaigy/php_n/bin/php-config --with-libmemcached-dir="/home/zhaigy/libmemcached_n"
make
make install
--顺利
安装到php
cd /home/zhaigy/php_n/
mkdir modules
cp /home/zhaigy/php_n/lib/php/extensions/no-debug-non-zts-20090626/memcached.so ./modules
php.ini中添加
extension = memcached.so
cd /home/zhaigy/apache_n
./bin/apachectl restart
从phpinfo中查看,正常

memcache 服务器端分析--libevent队列 线程模型


目前网上关于memcached的分析主要是内存管理部分,下面对memcached的线程模型做下简单分析 

有不对的地方还请大家指正,对memcahced和libevent不熟悉的请先google之 
先看下memcahced启动时线程处理的流程 

memcache 服务器端分析--libevent队列 线程模型 - zhengjunwei2007 - 我的博客
 
memcached的多线程主要是通过实例化多个libevent实现的,分别是一个主线程和n个workers线程 
无论是主线程还是workers线程全部通过libevent管理网络事件,实际上每个线程都是一个单独的libevent实例 
主线程负责监听客户端的建立连接请求,以及accept 连接 
workers线程负责处理已经建立好的连接的读写等事件 
先看一下大致的图示: 
memcache 服务器端分析--libevent队列 线程模型 - zhengjunwei2007 - 我的博客

实战Memcached缓存系统(5)Memcached的CAS程序实例


尊重知识,转载请注明本文来自:编程艺术家Poechant的CSDN博客 http://blog.csdn.net/poechant

1. 非CAS
首先看一个不是CAS的Memcached程序实例。实例的问题原型,见上一篇博文。
程序实例:
package com.sinosuperman.memcached;
 
import java.io.IOException;
import java.net.InetSocketAddress;
 
import net.spy.memcached.MemcachedClient;
 
public class Test {
    public static void main(String[] args) throws IOException {
        MemcachedClient cache = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211));
         
        cache.set("x", 1800, "Love");
 
        String obj1 = (String) cache.get("x");
        String obj2 = (String) cache.get("x");
        obj2 = "Michael";
         
        cache.set("x", 1800, obj2);
        System.out.println("Non-CAS 2:\t" + obj2);
        System.out.println("Non-CAS 1:\t" + obj1);
    }
}



运行结果:
2011-12-18 23:12:39.836 INFO net.spy.memcached.MemcachedConnection:  Added {QA sa=/127.0.0.1:11211, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue
2011-12-18 23:12:39.843 INFO net.spy.memcached.MemcachedConnection:  Connection state changed for sun.nio.ch.SelectionKeyImpl@b09e89
Non-CAS 2:  Michael
Non-CAS 1:  Love


可见在多个Client操作时,一定会引起写不一致性的问题。

2. CAS
程序实例:
package com.sinosuperman.memcached;
 
import java.io.IOException;
import java.net.InetSocketAddress;
 
import net.spy.memcached.CASValue;
import net.spy.memcached.MemcachedClient;
 
public class Test {
    @SuppressWarnings("unchecked")
    public static void main(String[] args) throws IOException {
        MemcachedClient cache = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211));
         
        cache.set("y", 1800, "Love");
 
        CASValue casValue1 = cache.gets("y");
        CASValue casValue2 = cache.gets("y");
        cache.cas("y", casValue2.getCas(), casValue2.getValue());
         
        System.out.println("CAS 2:\t" + casValue2.getCas());
        System.out.println("Value 2:\t" + casValue2.getValue());
         
        System.out.println("CAS 1:\t" + casValue1.getCas());
        System.out.println("Value 1:\t" + casValue1.getValue());
    }
}

运行结果:
2011-12-18 23:07:14.528 INFO net.spy.memcached.MemcachedConnection:  Added {QA sa=/127.0.0.1:11211, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue
2011-12-18 23:07:14.541 INFO net.spy.memcached.MemcachedConnection:  Connection state changed for sun.nio.ch.SelectionKeyImpl@1621e42
CAS 2:  11
Value 2:    Love
CAS 1:  11
Value 1:    Love

实战Memcached缓存系统(7)Memcached的一些基础FAQ



尊重知识,转载请注明本文来自:编程艺术家Poechant的CSDN博客 http://blog.csdn.net/poechant

1. Memcached是什么?
Memcached是分布式的内存对象缓存系统。


2. Memcached的基本数据结构是什么?
Memcached是基于Key/Value对的HashMap。每一对,都可以设定过期时间。


3. Memcached用什么实现?
服务端程序由C语言编写,客户端可以用任何语言编写。客户端通过Memcached协议与服务端通信。


4. Memcached特点
(1)无备份/冗余:
各Memcached节点的数据之间没有互相备份,一旦某个节点挂掉,缓存中的数据就会丢失。


5. 开发团队
Memcached由Danga Interactive开发。


6. 相关下载
(1)Memcached服务端程序
http://memcached.org/


(2)Memcached的客户端程序
http://code.google.com/p/memcached/wiki/Clients


(3)Memcached可视化管理系统(PHP和jQuery编写)
http://www.junopen.com/memadmin

7. 如何理解Memcached的分布式特点?
Memcached Server并不具有分布式特征,每个Server都是独立运行的,各Server之间不存在通信获知其他节点状态和数据备份的功能。那么Memcached为什么还是分布式的缓存系统呢?其实说到Memcached的分布式,是将Memcached Client结合在一起考虑的。具体的分布式策略,由Client实现。也就是说Memcached的分布式,不是系统层的,而是应用层的。

实战Memcached缓存系统(4)Memcached的CAS协议


尊重知识,转载请注明本文来自:编程艺术家Poechant的CSDN博客 http://blog.csdn.net/poechant

1. 什么是CAS协议
很多中文的资料都不会告诉大家CAS的全称是什么,不过一定不要把CAS当作中国科学院(China Academy of Sciences)的缩写。Google.com一下,CAS是什么?CAS是Check And Set的缩写。

2. CAS协议原文
http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt

3. CAS的基本原理
基本原理非常简单,一言以蔽之,就是“版本号”。每个存储的数据对象,多有一个版本号。我们可以从下面的例子来理解:
如果不采用CAS,则有如下的情景:
第一步,A取出数据对象X;
第二步,B取出数据对象X;
第三步,B修改数据对象X,并将其放入缓存;
第四步,A修改数据对象X,并将其放入缓存。
我们可以发现,第四步中会产生数据写入冲突。

如果采用CAS协议,则是如下的情景。
第一步,A取出数据对象X,并获取到CAS-ID1;
第二步,B取出数据对象X,并获取到CAS-ID2;
第三步,B修改数据对象X,在写入缓存前,检查CAS-ID与缓存空间中该数据的CAS-ID是否一致。结果是“一致”,就将修改后的带有CAS-ID2的X写入到缓存。
第四步,A修改数据对象Y,在写入缓存前,检查CAS-ID与缓存空间中该数据的CAS-ID是否一致。结果是“不一致”,则拒绝写入,返回存储失败。

这样CAS协议就用了“版本号”的思想,解决了冲突问题。

实战Memcached缓存系统(2)Memcached Java API基础之MemcachedClient




尊重知识,转载请注明本文来自:编程艺术家Poechant的CSDN博客 http://blog.csdn.net/poechant

1. 构造函数
public MemcachedClient(InetSocketAddress[] ia) throws IOException;

public MemcachedClient(List<InetSocketAddress> addrs) throws IOException;

public MemcachedClient(ConnectionFactory cf, List<InetSocketAddress> addrs) throws IOException;

其中最简单的构造函数就是第一个,可以直接传递一个InetSocketAddress,也可以是InetSocketAddress的数组。其实InetSocketAddress也是被转换成数组的。
比如:
MemcachedClient cache = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211));



2. 常用方法
一般缓存数据的常用操作有:set(add+replace)、get、replace、add

public Future<Boolean> set(String key, int exp, Object o)

第一个参数:键(key)
第二个参数:过期时间(单位是秒)
第三个参数:要设置缓存中的对象(value),如果没有则插入,如果有则修改。

public Object get(String key)

第一个参数:键(key)

public Future<Boolean> replace(String key, int exp, Object o)

第一个参数:键(key)
第二个参数:过期时间(单位是秒)
第三个参数:该键的新值(new value),如果有则修改。

public Future<Boolean> add(String key, int exp, Object o)

第一个参数:键(key)
第二个参数:过期时间(单位是秒)
第三个参数:该键的值(value),如果没有则插入。

尊重知识,转载请注明本文来自:编程艺术家Poechant的CSDN博客 http://blog.csdn.net/poechant

实战Memcached缓存系统(3)Memcached配置参数初解



尊重知识,转载请注明本文来自:编程艺术家Poechant的CSDN博客 http://blog.csdn.net/poechant

一、基本参数
在我们第一次安装Memcached时,一般都是用过这个命令:
memcached -m 512 -u root -d -l 127.0.0.1 -p 11211

我们先来解释这几个参数的含义吧。

-m 指定缓存所使用的最大内存容量,单位是Megabytes,默认是64MB
-u 只有以root身份运行时才指定该参数
-d 以daemon的形式运行
-l 指定监听的地址
-p 指定监听的TCP端口号,默认是11211

二、其他常用的参数
-t 指定线程数,默认是4个
-h 打印帮助信息
-c 最大同时连接数,默认是1024.
-U 指定监听的UDP端口号,默认是11211
-M 内存耗尽时显示错误,而不是删除项

一开始说的“-d”参数需要进行进一步的解释
-d install 安装memcached
-d uninstall 卸载memcached
-d start 启动memcached服务
-d restart 重启memcached服务
-d stop 停止memcached服务
-d shutdown 停止memcached服务

三、更多参数
使用"-h"去了解吧~

四、使用服务软件的经验
写到这里,最后说一句。在使用任何软件的时候,首先要去关注这样几点:

1. 打印帮助信息:
这个一般都是“-h”,当然也有需要“-help”才可以的。

2. 启动、停止、重启/重载配置的命令:
要注意,是同一个命令的不同参数来标识的,还是用不同的命令或脚本。

3. 配置
首先,启动是否需要配置文件。
其次,如果是比较大型的软件,一般都需要配置文件,那么默认的配置文件在哪里要清楚。
再次,指定加载配置文件的命令格式如何。

4. 指定使用内存容量、线程数、硬盘容量等
是否有这方面的配置参数需要指定,以及如何设置。

5. 日志文件
首先,是否有日志文件需要存储。
其次,如果有日志文件,默认的存储目录是什么。
最后,手动指定日志文件的命令格式如何。

6. 最大连接数
首先,是否提供监听的连接服务。
其次,如果提供,默认的最大连接数是多少。
最后,手动指定最大连接数的命令格式如何。

尊重知识,转载请注明本文来自:编程艺术家Poechant的CSDN博客 http://blog.csdn.net/poechant
-

实战Memcached缓存系统(1)Memcached基础及示例程序


尊重知识,转载请注明本文来自:编程艺术家Poechant的CSDN博客 http://blog.csdn.net/potent

1、Cache定义
(1)狭义概念:用于CPU的相对高速处理与主存(Main Memory)的相对低速处理的之间起到协调功能的硬件设备。
(2)广义概念:用于速度相差较大的两种硬件之间,起到协调两者数据传输速度差异的结构。
狭义概念来自于Cache自1967出现以来较长时间内的应用场景。因为CPU的数据处理速度,要远远高于主存,所以在CPU和主存之间会有高速缓存设备,甚至是多级缓存设备。而广义概念,则是目前已经被广泛接受的一种定义,且广义概念中,Cache不再只局限于硬件,也可以是软件。比如用于网络相对低速传输与磁盘相对高速传输之间的速度差异协调。


2、Cache的本质原理
可以一句话概括,就是:Cache把要到慢速设备中取的数据预先放到快速设备中。


3、几种类型的Cache
(1)CPU Cache:置于CPU和主存之间,用于加速CPU对主存的相对慢速操作。
(2)Browser Cache:置于客户端与服务器之间,用于加速客户端对服务器的相对慢速操作。
(3)Server Cache:置于网络请求与本地文件之间,用于加速网络请求对本地文件的相对慢速操作。
(4)CDN:CDN即Content Delivery Network,在各地设置的节点Cache,加速用户对服务网络的相对慢速操作。
(5)Database Cache
(6)OS Cache:内存中存在的对于硬盘读写的缓冲区域。

4、What is Memcached?
Memcached是一个免费开源、高性能、分布式的内存对象缓存系统。Memcached是在内存中,为特定数据(字符串或对象)构建key-value的小块数据存储。

5、下载Memcached的服务器端软件
Windows平台版本下载:http://splinedancer.com/memcached-win32/memcached-1.2.4-Win32-Preview-20080309_bin.zip
Linux平台版本下载:http://memcached.googlecode.com/files/memcached-1.4.10.tar.gz

6、在服务器上部署Memcached Server
以下以Windows平台为例:
参考:http://www.codeforest.net/how-to-install-memcached-on-windows-machine
下载下来的Windows版本解压到C:/memcached/
在控制台输入命令安装:
c:/memcached/memcached.exe  -d install

启动:
c:/memcached/memcached.exe -d  start

或:
net start "memcached Server"

默认的缓存大小为64M,如果不够用,请打开注册表,找到:
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/memcached  Server .

将其内容修改为:
“C:/memcached/memcached.exe” -d runservice -m 512


7、下载Memcached的客户端API包
下载地址:http://spymemcached.googlecode.com/files/memcached-2.5.jar

8、编写一个Java数据类
package com.sinosuperman.memcached;
 
import java.io.Serializable;
 
 
public class User implements Serializable{  
 
    private static final long serialVersionUID = -372274003834027815L;
 
    String userId;
     
    public User(String userId) {  
        super();  
        this.userId = userId;  
    }
     
    public String getUserId() {  
        return userId;  
    }  
     
    public void setUserId(String userId) {  
        this.userId = userId;  
    }  
         
    @Override  
    public String toString() {  
        // TODO Auto-generated method stub  
        StringBuffer sb=new StringBuffer();  
        sb.append("userId="+this.userId);  
        return sb.toString();  
    }  
}  


9、编写一个Memcached的客户端
package com.sinosuperman.memcached;
 
import java.io.IOException;
import java.net.InetSocketAddress;
 
import net.spy.memcached.MemcachedClient;
 
public class TestMemcached {
    public static void main(String[] args) throws IOException {
        MemcachedClient cache = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211));
        for (int i = 1; i < 10; i++) {
            cache.set("T0001" + i, 3600, new User(i + ""));  
        }
        User myObject = (User) cache.get("T00011");
        System.out.println("Get object from mem :" + myObject);  
    }  
}

10、运行测试
运行结果应该如下:
2011-12-15 17:25:30.276 INFO net.spy.memcached.MemcachedConnection:  Added {QA sa=/127.0.0.1:11211, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue
2011-12-15 17:25:30.292 INFO net.spy.memcached.MemcachedConnection:  Connection state changed for sun.nio.ch.SelectionKeyImpl@c62080
Get object from mem :userId=1

memcached完全剖析–1. memcached的基础

翻译一篇技术评论社的文章,是讲memcached的连载。fcicq同学说这个东西很有用,希望大家喜欢。
我是mixi株式会社开发部系统运营组的长野。 日常负责程序的运营。从今天开始,将分几次针对最近在Web应用的可扩展性领域 的热门话题memcached,与我公司开发部研究开发组的前坂一起, 说明其内部结构和使用。

memcached是什么?

memcached 是以LiveJournal 旗下Danga Interactive 公司的Brad Fitzpatric 为首开发的一款软件。现在已成为 mixi、 hatenaFacebook、 Vox、LiveJournal等众多服务中 提高Web应用扩展性的重要因素。
许多Web应用都将数据保存到RDBMS中,应用服务器从中读取数据并在浏览器中显示。 但随着数据量的增大、访问的集中,就会出现RDBMS的负担加重、数据库响应恶化、 网站显示延迟等重大影响。
这时就该memcached大显身手了。memcached是高性能的分布式内存缓存服务器。 一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、 提高可扩展性。
memcached-0001-01.png
图1 一般情况下memcached的用途

memcached的特征

memcached作为高速运行的分布式缓存服务器,具有以下的特点。
  • 协议简单
  • 基于libevent的事件处理
  • 内置内存存储方式
  • memcached不互相通信的分布式

协议简单

memcached的服务器客户端通信并不使用复杂的XML等格式, 而使用简单的基于文本行的协议。因此,通过telnet 也能在memcached上保存数据、取得数据。下面是例子。
$ telnet localhost 11211 Trying 127.0.0.1... Connected to localhost.localdomain (127.0.0.1). Escape character is '^]'. set foo 0 0 3 (保存命令) bar (数据) STORED (结果) get foo (取得命令) VALUE foo 0 3 (数据) bar (数据)
协议文档位于memcached的源代码内,也可以参考以下的URL。

基于libevent的事件处理

libevent是个程序库,它将Linux的epoll、BSD类操作系统的kqueue等事件处理功能 封装成统一的接口。即使对服务器的连接数增加,也能发挥O(1)的性能。 memcached使用这个libevent库,因此能在Linux、BSD、Solaris等操作系统上发挥其高性能。 关于事件处理这里就不再详细介绍,可以参考Dan Kegel的The C10K Problem。

内置内存存储方式

为了提高性能,memcached中保存的数据都存储在memcached内置的内存存储空间中。 由于数据仅存在于内存中,因此重启memcached、重启操作系统会导致全部数据消失。 另外,内容容量达到指定值之后,就基于LRU(Least Recently Used)算法自动删除不使用的缓存。 memcached本身是为缓存而设计的服务器,因此并没有过多考虑数据的永久性问题。 关于内存存储的详细信息,本连载的第二讲以后前坂会进行介绍,请届时参考。

memcached不互相通信的分布式

memcached尽管是“分布式”缓存服务器,但服务器端并没有分布式功能。 各个memcached不会互相通信以共享信息。那么,怎样进行分布式呢? 这完全取决于客户端的实现。本连载也将介绍memcached的分布式。
memcached-0001-02.png
图2 memcached的分布式
接下来简单介绍一下memcached的使用方法。

安装memcached

memcached的安装比较简单,这里稍加说明。
memcached支持许多平台。 * Linux * FreeBSD * Solaris (memcached 1.2.5以上版本) * Mac OS X
另外也能安装在Windows上。这里使用Fedora Core 8进行说明。

memcached的安装

运行memcached需要本文开头介绍的libevent库。Fedora 8中有现成的rpm包, 通过yum命令安装即可。
$ sudo yum install libevent libevent-devel
memcached的源代码可以从memcached网站上下载。本文执笔时的最新版本为1.2.5。 Fedora 8虽然也包含了memcached的rpm,但版本比较老。因为源代码安装并不困难, 这里就不使用rpm了。
memcached安装与一般应用程序相同,configure、make、make install就行了。
$ 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下。

memcached的启动

从终端输入以下命令,启动memcached。
$ /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)
这里显示了调试信息。这样就在前台启动了memcached,监听TCP端口11211 最大内存使用量为64M。调试信息的内容大部分是关于存储的信息, 下次连载时具体说明。
作为daemon后台启动时,只需
$ /usr/local/bin/memcached -p 11211 -m 64m -d
这里使用的memcached启动选项的内容如下。
选项说明
-p使用的TCP端口。默认为11211
-m最大内存大小。默认为64M
-vv用very vrebose模式启动,调试信息和错误输出到控制台
-d作为daemon在后台启动
上面四个是常用的启动选项,其他还有很多,通过
$ /usr/local/bin/memcached -h
命令可以显示。许多选项可以改变memcached的各种行为, 推荐读一读。

用客户端连接

许多语言都实现了连接memcached的客户端,其中以Perl、PHP为主。 仅仅memcached网站上列出的语言就有
  • Perl
  • PHP
  • Python
  • Ruby
  • C#
  • C/C++
  • Lua
等等。
这里介绍通过mixi正在使用的Perl库链接memcached的方法。

使用Cache::Memcached

Perl的memcached客户端有
  • Cache::Memcached
  • Cache::Memcached::Fast
  • Cache::Memcached::libmemcached
等几个CPAN模块。这里介绍的Cache::Memcached是memcached的作者Brad Fitzpatric的作品, 应该算是memcached的客户端中应用最为广泛的模块了。

使用Cache::Memcached连接memcached

下面的源代码为通过Cache::Memcached连接刚才启动的memcached的例子。
#!/usr/bin/perl use strict; use warnings; use Cache::Memcached; my $key = "foo"; my $value = "bar"; my $expires = 3600; # 1 hour my $memcached = Cache::Memcached->new({ servers => ["127.0.0.1:11211"], compress_threshold => 10_000 }); $memcached->add($key, $value, $expires); my $ret = $memcached->get($key); print "$ret\n";
在这里,为Cache::Memcached指定了memcached服务器的IP地址和一个选项,以生成实例。 Cache::Memcached常用的选项如下所示。
选项说明
servers用数组指定memcached服务器和端口
compress_threshold数据压缩时使用的值
namespace指定添加到键的前缀
另外,Cache::Memcached通过Storable模块可以将Perl的复杂数据序列化之后再保存, 因此散列、数组、对象等都可以直接保存到memcached中。

保存数据

向memcached保存数据的方法有
  • add
  • replace
  • set
它们的使用方法都相同:
my $add = $memcached->add( '键', '值', '期限' ); my $replace = $memcached->replace( '键', '值', '期限' ); my $set = $memcached->set( '键', '值', '期限' );
向memcached保存数据时可以指定期限(秒)。不指定期限时,memcached按照LRU算法保存数据。 这三个方法的区别如下:
选项说明
add仅当存储空间中不存在键相同的数据时才保存
replace仅当存储空间中存在键相同的数据时才保存
set与add和replace不同,无论何时都保存

获取数据

获取数据可以使用get和get_multi方法。
my $val = $memcached->get('键'); my $val = $memcached->get_multi('键1', '键2', '键3', '键4', '键5');
一次取得多条数据时使用getmulti。getmulti可以非同步地同时取得多个键值, 其速度要比循环调用get快数十倍。

删除数据

删除数据使用delete方法,不过它有个独特的功能。
$memcached->delete('键', '阻塞时间(秒)');
删除第一个参数指定的键的数据。第二个参数指定一个时间值,可以禁止使用同样的键保存新数据。 此功能可以用于防止缓存数据的不完整。但是要注意,set函数忽视该阻塞,照常保存数据

增一和减一操作

可以将memcached上特定的键值作为计数器使用。
my $ret = $memcached->incr('键'); $memcached->add('键', 0) unless defined $ret;
增一和减一是原子操作,但未设置初始值时,不会自动赋成0。因此, 应当进行错误检查,必要时加入初始化操作。而且,服务器端也不会对 超过2 SUP(32)时的行为进行检查。

总结

这次简单介绍了memcached,以及它的安装方法、Perl客户端Cache::Memcached的用法。 只要知道,memcached的使用方法十分简单就足够了。
下次由前坂来说明memcached的内部结构。了解memcached的内部构造, 就能知道如何使用memcached才能使Web应用的速度更上一层楼。 欢迎继续阅读下一章。