仕事が忙しくてずいぶん間が空いてしまったのだが、またTT/TCをいじり始めています。 実は性能が出なくて困っていた。特に 20万件を越えたあたりからライトが激烈に遅く ちょっと使い物にならないレベルに。
で、ちょっとぐぐったらとても良い資料見つけました。 SSDとTokyoTyrantやMySQLの性能検証(by 株式会社ゆめみ)。 こんなノウハウを惜しげもなく公開してくれるなんて....大変ありがたい。
所詮HDDだろうがSSDだろうがディスクI/Oが混むと手のつけようがないので、 「メモリ大量に用意してxmsizデカくしてオンメモリで処理しろ」 というアプローチが 正道らしい。
TC/TT開発者mikioさんがブログ等でTTを「状態をディスクに保持してくれるmemcached」という 立ち位置で説明してるので誤解しやすい(俺だけかもしらんが俺は誤解してた)けど、 やっぱりメモリ最強 ということですか....。
具体的にはttserverを起動するdbname行にxmsiz指定をつける(パラメータは256mとか1gとか)。
cascket.tct#xmsiz=1g#opts=ld#apow=6#dfunit=4
みたいな感じ。ウチでは80万件のデータベースに対してキャッシュ1G指定したら、 だいたいライトが80倍くらいになりました(今までは何だったの....)。 データベース全体は600MBくらいなのでまるっきりメモリに入ってしまう模様。
通常、Perlにおける、TTのRDBTBL(SQLライクなテーブル状データへのアクセス)に対する検索の 贋コードは以下のとおり。概ね「ptokenカラム内をタグ検索して、ptime順にオーダーして、最大100件出力」という意味です。
my $qry = TokyoTyrant::RDBQRY->new($pm); $qry->addcond('ptoken', $qry->QCSTRAND, $tokens); $qry->setlimit(100); $qry->setorder('ptime', $qry->QONUMASC); my $rv = $qry->search();
ここで$rvに返ってくるのは キーリストのリファレンス である。なので、 以下のようにforeachで回したくなる。get関数は指定キーのデータ本体をとってくるものね。
foreach my $rkey (@$rv) { my $rcols = $pm->get($rkey); # print Dumper($rcols); }
しかしこれは遅いのだ。 TT/TCにはmget関数というものが用意されている。 mget関数は あらかじめキーを入れたハッシュのリファレンスを渡す と、 データが存在するものは値セットしてくれ、データがないものはキーごと削除してくれる...らしい。 getだと毎回サーバに対してリクエストを出してしまうけれど、mgetだと1回で済むわけだ。
mgetを使った贋コードは以下のとおり。リストはmap関数でハッシュに直しています。
my %rtable = map { $_=>undef } @$rv; my $count = $pm->mget(\%rtable); foreach my $rkey (@$rv) { next if (!exists $rtable{$rkey}); my $rcols = $rtable{$rkey}; # print Dumper($rcols); }
結果... MGET:0.006553sec GET:0.030858sec ということで mgetはgetのおよそ4.7倍 という結果でした。 ああ、俺が使い方知らなかっただけなのね。これは便利だし副作用ないしガンガン使っていこう。
それでも私の環境では数万QPSにはまったく届きません。Core i3でもPhenomII X4でも。 特にライトは1000QPS出ているかでていないかで、件のレポートでいう「極端に悪い状況」です。 まあメモリ4GBしかないので、せいぜいttserverに割り当てられるキャッシュメモリは1GBということもあるけど。
なんでだろう...と思っていろいろ試しているのですが、確定的なことは言えません。
でも、ttserverを同じマシンで10コ起動するという場面は、 もしかして想定してない? と は思っています。
通常のSQLデータベースだと、1サーバ<複数データベース<複数テーブルという階層構造で、 通信用のワーカースレッドが複数個立ち上がっても、データベース自体の書き込みは比較的シリアライズされていると 考えられます。
しかしttserverの場合は1サーバ=1データベース=1テーブルという単一構造で、 どうしても実用的なアプリケーションを作成しようとすると、複数個ttserverを起動したくなる訳ですが、 どうも 全員がガムシャラにディスクをアクセスするよう なんですよね....常に全力全開マジモードで。
avg-cpu: %user %nice %system %iowait %steal %idle 0.00 0.00 0.05 32.62 0.00 67.33 Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn sda 27.00 0.00 1206.40 0 6032
これは...O/Rマッパーを書いて複数のテーブルを1つのttserverに押し込めるように したほうが良かったですかね。