memcached for perl

來源:互聯網
上載者:User

用到memcached,記下

 memcached中儲存的資料都儲存在memcached內建的記憶體儲存空間中。
由於資料僅存在於記憶體中,因此重啟memcached、重啟作業系統會導致全部資料消失。
另外,內容容量達到指定值之後,就基於LRU(Least Recently Used)演算法自動刪除不使用的緩衝。
memcached本身是為緩衝而設計的伺服器,因此並沒有過多考慮資料的永久性問題。

 memcached是“分布式”快取服務器,但伺服器端並沒有分布式功能。
各個memcached不會互相通訊以共用資訊。進行分布式完全取決於用戶端的實現。

memcached需要 libevent庫 #yum install libevent libevent-devel

 

$ wget http://www.danga.com/memcached/dist/memcached-1.×.×.tar.gz
$ tar zxf memcached-1.×.×.tar.gz
$ cd memcached-1.×.×$ ./configure
$ make
$ sudo make install
#/usr/local/bin/memcached -p 11211 -m 64m -d
選項 說明
-p 使用的TCP連接埠。預設為11211
-m 最大記憶體大小。預設為64M
-vv 用very vrebose模式啟動,調試資訊和錯誤輸出到控制台
-d 作為daemon在後台啟動

memcached用戶端API
:http://www.danga.com/memcached/apis.bml

Perl的memcached用戶端有

  • Cache::Memcached
  • Cache::Memcached::Fast
  • Cache::Memcached::libmemcached

等幾個CPAN模組。

  http://search.cpan.org/dist/Cache-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。因此,
應當進行錯誤檢查,必要時加入初始化操作。

Cache::Memcached的分布式方法

Perl的memcached用戶端函數庫Cache::Memcached是
memcached的作者Brad Fitzpatrick的作品,可以說是原裝的函數庫了。

  • Cache::Memcached - search.cpan.org

該函數庫實現了分布式功能,是memcached標準的分布式方法。

根據餘數計算分散

Cache::Memcached的分布式方法簡單來說,就是“根據伺服器台數的餘數進行分散”。
求得鍵的整數雜湊值,再除以伺服器台數,根據其餘數來選擇伺服器。

下面將Cache::Memcached簡化成以下的Perl指令碼來進行說明。

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値
my $mod = $crc % ( $#nodes + 1 );
my $server = $nodes[ $mod ]; # 根據餘數選擇伺服器
printf "%s => %s/n", $key, $server;
}

Cache::Memcached在求雜湊值時使用了CRC。

  • String::CRC32 - search.cpan.org

首先求得字串的CRC值,根據該值除以伺服器節點數目得到的餘數決定伺服器。
上面的代碼執行後輸入以下結果:

tokyo       => node2
kanagawa => node3
chiba => node2
saitama => node1
gunma => node1

根據該結果,“tokyo”分散到node2,“kanagawa”分散到node3等。
多說一句,當選擇的伺服器無法串連時,Cache::Memcached會將串連次數
添加到鍵之後,再次計算雜湊值並嘗試串連。這個動作稱為rehash。
不希望rehash時可以在產生Cache::Memcached對象時指定“rehash => 0”選項。

根據餘數計算分散的缺點

餘數計算的方法簡單,資料的分散性也相當優秀,但也有其缺點。
那就是當添加或移除伺服器時,緩衝重組的代價相當巨大。
添加伺服器後,餘數就會產生巨變,這樣就無法擷取與儲存時相同的伺服器,
從而影響緩衝的命中率。用Perl寫段代碼來驗證其代價。

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

這段Perl指令碼示範了將“a”到“z”的鍵儲存到memcached並訪問的情況。
將其儲存為mod.pl並執行。

首先,當伺服器只有三台時:

$ 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

結果如上,node1儲存a、c、d、e……,node2儲存g、i、k……,
每台伺服器都儲存了8個到10個資料。

接下來增加一台memcached伺服器。

$ 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,z

添加了node4。可見,只有d、i、k、p、r、y命中了。像這樣,添加節點後
鍵分散到的伺服器會發生巨大變化。26個鍵中只有六個在訪問原來的伺服器,
其他的全都移到了其他伺服器。命中率降低到23%。在Web應用程式中使用memcached時,
在添加memcached伺服器的瞬間緩衝效率會大幅度下降,負載會集中到資料庫伺服器上,
有可能會發生無法提供正常服務的情況。

mixi的Web應用程式運用中也有這個問題,導致無法添加memcached伺服器。
但由於使用了新的分布式方法,現在可以輕而易舉地添加memcached伺服器了。
這種分布式方法稱為 Consistent Hashing。

Consistent Hashing

關於Consistent Hashing的思想,mixi株式會社的開發blog等許多地方都介紹過,
這裡只簡單地說明一下。

  • mixi Engineers' Blog - スマートな分散で快適キャッシュライフ
  • ConsistentHashing - コンシステント ハッシュ法
Consistent Hashing的簡單說明

Consistent Hashing如下所示:首先求出memcached伺服器(節點)的雜湊值,
並將其配置到0~232
的圓(continuum)上。
然後用同樣的方法求出儲存資料的鍵的雜湊值,並映射到圓上。
然後從資料對應到的位置開始順時針尋找,將資料儲存到找到的第一個伺服器上。
如果超過232
仍然找不到伺服器,就會儲存到第一台memcached伺服器上。

圖4 Consistent Hashing:基本原理

從的狀態中添加一台memcached伺服器。餘數分布式演算法由於儲存鍵的伺服器會發生巨大變化
而影響緩衝的命中率,但Consistent Hashing中,只有在continuum上增加伺服器的地點逆時針方向的
第一台伺服器上的鍵會受到影響。

圖5 Consistent Hashing:添加伺服器

因此,Consistent Hashing最大限度地抑制了鍵的重新分配。
而且,有的Consistent Hashing的實現方法還採用了虛擬節點的思想。
使用一般的hash函數的話,伺服器的映射地點的分布非常不均勻。
因此,使用虛擬節點的思想,為每個物理節點(伺服器)
在continuum上分配100~200個點。這樣就能抑制分布不均勻,
最大限度地減小伺服器增減時的緩衝重新分配。

通過下文中介紹的使用Consistent Hashing演算法的memcached用戶端函數庫進行測試的結果是,
由伺服器台數(n)和增加的伺服器台數(m)計算增加伺服器後的命中率計算公式如下:

(1 - n/(n+m)) * 100

支援Consistent Hashing的函數庫

本連載中多次介紹的Cache::Memcached雖然不支援Consistent Hashing,
但已有幾個用戶端函數庫支援了這種新的分布式演算法。
第一個支援Consistent Hashing和虛擬節點的memcached用戶端函數庫是
名為libketama的PHP庫,由last.fm開發。

  • libketama - a consistent hashing algo for memcache clients – RJ ブログ - Users at Last.fm

至於Perl用戶端,連載的第1次
中介紹過的Cache::Memcached::Fast和Cache::Memcached::libmemcached支援
Consistent Hashing。

  • Cache::Memcached::Fast - search.cpan.org
  • Cache::Memcached::libmemcached - search.cpan.org

兩者的介面都與Cache::Memcached幾乎相同,如果正在使用Cache::Memcached,
那麼就可以方便地替換過來。Cache::Memcached::Fast重新實現了libketama,
使用Consistent Hashing建立對象時可以指定ketama_points選項。

my $memcached = Cache::Memcached::Fast->new({
servers => ["192.168.0.1:11211","192.168.0.2:11211"],
ketama_points => 150
});

另外,Cache::Memcached::libmemcached 是一個使用了Brain Aker開發的C函數庫libmemcached的Perl模組。
libmemcached本身支援幾種分布式演算法,也支援Consistent Hashing,
其Perl綁定也支援Consistent Hashing。

  • Tangent Software: libmemcached
曆史上的今天:網站安全
2008-07-29收藏到:Del.icio.us
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.