memcached

 

我是mixi株式會社開發部系統運營組的長野。日常負責程序的運營。從今天開始,將分幾次針對最近在Web應用的可擴展性領域的熱門話題memcached,與我公司開發部研究開發組的前阪一起,說明其內部結構和使用。

<!-- end Pukiwiki generated code-->

 

<!-- begin Pukiwiki generated code-->

memcached是什麼?

memcached 是以LiveJournal 旗下Danga Interactive 公司的Brad Fitzpatric 爲首開發的一款軟件。現在已成爲 mixihatenaFacebookVox、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');

一次取得多條數據時使用get_multi。get_multi可以非同步地同時取得多個鍵值,其速度要比循環調用get快數十倍。

刪除數據

刪除數據使用delete方法,不過它有個獨特的功能。

$memcached->delete('鍵', '阻塞時間(秒)');

刪除第一個參數指定的鍵的數據。第二個參數指定一個時間值,可以禁止使用同樣的鍵保存新數據。此功能可以用於防止緩存數據的不完整。但是要注意,set函數忽視該阻塞,照常保存數據

增一和減一操作

可以將memcached上特定的鍵值作爲計數器使用。

my $ret = $memcached->incr('鍵');
$memcached->add('鍵', 0) unless defined $ret;

增一和減一是原子操作,但未設置初始值時,不會自動賦成0。因此,應當進行錯誤檢查,必要時加入初始化操作。而且,服務器端也不會對超過2<sup>32</sup>時的行爲進行檢查。

總結

這次簡單介紹了memcached,以及它的安裝方法、Perl客戶端Cache::Memcached的用法。只要知道,memcached的使用方法十分簡單就足夠了。

下次由前阪來說明memcached的內部結構。瞭解memcached的內部構造,就能知道如何使用memcached才能使Web應用的速度更上一層樓。歡迎繼續閱讀下一章。

<!-- end Pukiwiki generated code-->

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章