memcached徹底剖析–memcached的基礎

memcached是什麼?

memcached 是以LiveJournal 旗下Danga Interactive 公司的Brad Fitzpatric 爲首開發的一款軟件。如今已成爲 mixi、 hatena、 Facebook、 Vox、LiveJournal等衆多服務中 提升Web應用擴展性的重要因素。javascript

許多Web應用都將數據保存到RDBMS中,應用服務器從中讀取數據並在瀏覽器中顯示。 但隨着數據量的增大、訪問的集中,就會出現RDBMS的負擔加劇、數據庫響應惡化、 網站顯示延遲等重大影響。php

這時就該memcached大顯身手了。memcached是高性能的分佈式內存緩存服務器。 通常的使用目的是,經過緩存數據庫查詢結果,減小數據庫訪問次數,以提升動態Web應用的速度、 提升可擴展性。html

memcached-0001-01.png

圖1 通常狀況下memcached的用途java

memcached的特徵

memcached做爲高速運行的分佈式緩存服務器,具備如下的特色。linux

  • 協議簡單
  • 基於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。windows

內置內存存儲方式

爲了提升性能,memcached中保存的數據都存儲在memcached內置的內存存儲空間中。 因爲數據僅存在於內存中,所以重啓memcached、重啓操做系統會致使所有數據消失。 另外,內容容量達到指定值以後,就基於LRU(Least Recently Used)算法自動刪除不使用的緩存。 memcached自己是爲緩存而設計的服務器,所以並無過多考慮數據的永久性問題。 關於內存存儲的詳細信息,本連載的第二講之後前阪會進行介紹,請屆時參考。api

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 32時的行爲進行檢查。

總結

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

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