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


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




0 件のコメント:

コメントを投稿