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

日期:2008-07-17  作者:喜騰小二  來源:PHPChina


版權宣告:可以任意轉載,但轉載時必須標明原作者charlee、原始連結http://tech.idv2.com/2008/07/10/memcached-001/以及本宣告。


翻譯一篇技術評論社的文章,是講memcached的連載。fcicq同學說這個東西很有用,希望大家喜歡。

發表日:2008/7/2
作者:長野雅廣(Masahiro Nagano)
原文連結:http://gihyo.jp/dev/feature/01/memcached/0001

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

  • memcached是什麼?
  • memcached的特徵
    • 協定簡單
    • 基於libevent的事件處理
    • 內建記憶體存儲方式
    • memcached不互相通信的分散式
  • 安裝memcached
    • memcached的安裝
    • memcached的啓動
  • 用用戶端連線
  • 使用Cache::Memcached
    • 使用Cache::Memcached連線memcached
    • 儲存資料
    • 獲取資料
    • 移除資料
    • 增一和減一操作
  • 總結

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
";

在這裡,為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。因此,應當進行錯誤檢查,必要時加入初始化操作。而且,伺服器端也不會對超過232時的行為進行檢查。

總結

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

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

<<<返回技術中心

技術文章

站內新聞