ラベル KyotoTycoon の投稿を表示しています。 すべての投稿を表示
ラベル KyotoTycoon の投稿を表示しています。 すべての投稿を表示

2011年12月30日金曜日

KyotoTycoon「memcachedプロトコルでメッセージキュー」を試す



最近低GIダイエットのブログを中心に書いている気がしますが、年末ということで少し時間ができたので前々から導入しようと思っていたKyotoTycoonのメッセージキューを試すことにしました。メッセージキューによる非同期処理といえば、Q4MとかActiveMQをよく使っていていますが、これもKyotoTycoonでいいんじゃない?と思うこの頃です。
何よりmemcachedプロトコルで動作するのがとても助かりますよね。

今回の内容はこちらです。


  • ktserver起動ファイル(マスター)

  • ktserver起動ファイル(スレーブ)

  • ジョブの登録(PHP)

  • ジョブの取得と削除(PHP)

  • ベンチマークの結果

  • テスト中に気になったこと

  • kctのデフラグ

  • Net_KyotoTycoonでキューの件数を取得する(PHP)




参考 memcachedプロトコルでメッセージキューを実現する
http://fallabs.com/blog-ja/promenade.cgi?id=133


テスト環境は、以前試したこちらですが、yum updateしてCentOS 6.2になりました。

ktserver起動ファイル(マスター)


まずは、damontoolsでktserverを起動します。
起動オプションですが、メッセージキューで動作させるには、「必ずツリー系のデータベース(GrassDB、TreeDB、ForestDB)のいずれかを指定してサーバを起動する必要がある」そうです。なので、オススメ通りTreeDBで。
thオプションは1でもよいそうですが、冗長構成のためレプリケーションの使用を前提に4にしました。


#!/bin/sh

PATH=/usr/local/bin:/usr/bin:/bin
PATH=$PATH:/usr/local/kyototycoon/bin
export PATH

exec env - PATH=$PATH \
ktserver \
-host 127.0.0.1 \
-port 10001 \
-th 4 \
-log /path/to/log/queue_master.log \
-ls \
-ulog /path/to/log/ulog_queue_master \
-ulim 256M \
-sid 1 \
-plsv /usr/local/kyototycoon/libexec/ktplugservmemc.so \
-plex 'port=11311#opts=fq' \
'/path/to/db/queue_master.kct#ktopts=p' 2>&1



ktserver起動ファイル(スレーブ)




#!/bin/sh

PATH=/usr/local/bin:/usr/bin:/bin
PATH=$PATH:/usr/local/kyototycoon/bin
export PATH

exec env - PATH=$PATH \
ktserver \
-host 127.0.0.1 \
-port 10002 \
-log /path/to/log/queue_slave.log \
-ls \
-ulog /path/to/log/ulog_queue_slave \
-ulim 256M \
-sid 2 \
-th 4 \
-mhost 127.0.0.1 \
-mport 10001 \
-rts /path/to/log/rts.log \
-plsv /usr/local/kyototycoon/libexec/ktplugservmemc.so \
-plex 'port=11312#opts=fq' \
'/path/to/db/queue_slave.kct#ktopts=p' 2>&1



ジョブの登録


このような非同期処理は、そもそもキューが溜まらないように処理していくはずなのですが、
性能評価なのである程度の件数(100万件×3の300万件)の平均値で計測します。

<?php

$data = array(
'name' => 'testname',
'testdata' =>
array(1,2,3,4,5,6,7,8,9,0,'abcdefghijklmnopqrstuvwxyz',
'userid' => 'testuserid',
'entry' => '2011-10-20 12:00:00'
)
);
$mem = new Memcached();
$mem->addServer('127.0.0.1', 11311);

$time_start = microtime(true);
for ($i = 0; $i < 1000000; $i++) {
$mem->set('testkey', $data);
}
$time_end = microtime(true);
echo ($time_end - $time_start) . "\n";



ジョブの取得と削除


ジョブは取得してその情報を元した処理が成功した後に削除することが想定されるため、1件ずつgetとdeleteを繰り返して計測します。

<?php

$key = 'testkey';
$m = new Memcached();
$m->addServer('127.0.0.1', 11311);

$cnt = 0;
$time_start = microtime(true);
for ($i = 0; $i < 1000000; $i++)
{
$val = $m->get($key);
if ($val)
{
$res = $m->delete($key);
if ($res)
{
$cnt++;
}
}
}
$time_end = microtime(true);
echo ($time_end - $time_start) . "\n";
echo $cnt . "\n";



バッチ処理によるベンチマークの結果









method性能(qps)
ジョブの登録(set)13806
ジョブの取得と削除(get & delete)6956

速度的にも申し分無く、ktserverの使用物理メモリーサイズも162mと少なく、kctファイルサイズ(300万件)も774Mでした。
また、setが高速なのは非同期処理に向いていると思います。
ちなみにkctのオプションに「#bnum=6000000#msiz=2g#pccap=2g」を追加して試してみたところget, deleteが10%ほど速くなりましたが、そもそも用途として1回のみの「登録」、「取得」、「削除」が想定されるので、富豪的にしてもあまり意味ないですね。

テスト中に気になったこと




  • データ削除してもkctファイルサイズが小さくならない。むしろ813Mと少し大きくなった。

  • kcやktの管理コマンドでキューのリアルタイムの件数が取得できない。-onl付けても無理。

これらは次の方法でなんとかなりそうです。

kctのデフラグ


デフラグするには、ktserverを停止してからkyotocabinetのkctreemgrコマンドを実行します。


kctreemgr defrag /path/to/queue_master.kct


今回の環境では、800MB程度ならおそらく2秒くらいで完了します。
デフラグは、そんなに肥大化しないと思うのとパフォーマンスには影響がなさそうなので、わざわざ止めてまでやる必要ないかもしれません。また、どうしてもやりたい場合も、スレーブ側を止めて切り替えるとかいろいろ手はあると思います。

Net_KyotoTycoonでキューの件数を取得する


あとkctreemgr、kttimedmgr 、ktremotemgrなどでキューの件数を取得してみましたが、ktserverを停止しないと正しい値(count)は取れなかったためNet_KyotoTycoonで取得することにしました。スレーブ側なら停止して取得してもよいかもしれませんが、APIで取得できるのでそこまでしなくてもいいですね。



  • 必要なモジュールのインストール

pear channel-discover openpear.org
pear config-set auto_discover 1
pear install pear.phpunit.de/PHPUnit
pear install HTTP_Request2
pear install openpear/Net_KyotoTycoon-beta


<?php

require_once 'Net/KyotoTycoon.php';
$kt = new \Net\KyotoTycoon(array('host' => '127.0.0.1', 'port' => 10001, 'timeout' => 5));
$res = $kt->status();
echo $res['count'] . "\n";


もうこれは使うしかないですね。




2011年10月20日木曜日

KyotoTycoon + KyotoCabinetのベンチマーク



KyotoTycoonが以前からすごく気になっていたのですが、
次の開発で導入すべく動作検証してみました。

まずは、KyotoTycoon + KyotoCabinet の気になるところを紹介すると。



  • DBがキャッシュ、B+ツリー、ハッシュなど選べる

  • ホットバックアップ

  • 非同期レプリケーション

  • デュアルマスタ

  • スナップショット これいいかも。lzo圧縮も効く。リカバリー用にも使える。

  • プラグインでmemcachedプロトコルが使える

  • lua拡張も使えるので、やろうと思えばなんでもあり。

  • noreplyを使うと何倍も速くなるらしい。

  • writebackで書き込むと何倍も速くなるらしい。

ブログがとても参考になります。
http://fallabs.com/blog-ja/promenade.cgi


テスト環境(DELL PowerEdge R200改)








CPUIntel Xeon CPU X3360 2.83GHz (4core)
メモリ8GB
HDD1TB (Hitachi HDT721010SLA360)
OSCentOS 6.0 (2.6.32-71.29.1.el6.x86_64)

KyotoCabinetインストール


yum install lzo-devel lzma-devel xz-devel
cd /usr/local/src
wget http://fallabs.com/kyotocabinet/pkg/kyotocabinet-1.2.70.tar.gz
tar zxfv kyotocabinet-1.2.70.tar.gz
cd kyotocabinet-1.2.70
./configure --prefix=/usr/local/kyotocabinet --enable-lzo --enable-lzma
make
make install
echo /usr/local/kyotocabinet/lib > /etc/ld.so.conf.d/kyotocabinet.conf
ldconfig


KyotoTycoonインストール


yum install lua-devel.x86_64
cd /usr/local/src
wget http://fallabs.com/kyototycoon/pkg/kyototycoon-0.9.51.tar.gz
tar zxfv kyototycoon-0.9.51.tar.gz
cd kyototycoon-0.9.51
./configure --prefix=/usr/local/kyototycoon --with-kc=/usr/local/kyotocabinet --enable-lua
make
make install
echo /usr/local/kyototycoon/lib > /etc/ld.so.conf.d/kyototycoon.conf
ldconfig


ktserver起動オプション


ktserver \
-port 11311 \
-tout 10 \
-th 16 \
-log /var/kt/log/ktserver.log -ls \
-ulog /var/kt/log/ulog -ulim 256m \
-sid 1 \
-bgs /var/kt/snapshot -bgsi 180 -bgsc lzo \
-pid /var/kt/log/kt.pid \
-cmd /var/kt/bin \
-plsv /usr/local/kyototycoon/libexec/ktplugservmemc.so \
-plex "port=11312#opts=f#tout=10" \
"/var/kt/db/casket.kch#opts=l#bnum=20000000#msiz=8g#dfunit=8"


性能評価は、使い慣れたPerlではなくあえてPHP。
daemontoolsでktserverを起動し、次のバッチを実行した。
PHPソースコード
<?php
$data = array(
    'name' => 'testname',
    'testdata' => 
        array(1,2,3,4,5,6,7,8,9,0,'abcdefghijklmnopqrstuvwxyz',
            'userid' => 'testuserid',
            'entry' => '2011-10-20 12:00:00'
        )
    );
$mem = new Memcached();
$mem->addServer('localhost',11312);
for ($i = 0; $i < 10000000; $i++) {
   $guid = md5(uniqid(mt_rand(),true)); 
   $guid = substr($guid,0,21);
   $mem->set($guid, $data);
}
※pecl memcached 2.0.0b2 (libmemcached 0.53)を使用。
perlならCache::Memcached::Fastで試しますね。

ベンチマーク結果




  • setの結果(1000万件登録)








使用メモリ2.0g
ファイルサイズ2.0g
スナップショット227M
性能12300qps


  • getの結果





性能15000qps

バッチ実行時はloadavgは常時1以下でかなり快適です。
チューニングの余地があるんでしょうが、
本番環境では常に負荷が低い方がよいこともあり、このままでも十分かも。
また、スナップショットのファイルサイズに感動ですね。
バックアップとか助かります。