2010/10/20

NoSQL redisとMySQLのベンチマーク比較

こんにちは、ミツバチワークス stoneです。

「NoSQL」という言葉を、最近知りました。
確かに、データベースをテーブルごとに小分けして行くと、トランザクションとか、SQLのjoinとか使わなくなって、DECOLOGでも、MySQLを単純なKey-Valueストア的な使い方をしている箇所がいくつかあります。

Key-Valueストアと言えば、DECOLOGでもmemcachedを使用していますが、memcachedのスピード感でデータが揮発しないというのは非常に魅力的です。
DECOLOGのデータ群の中でも、簡単なKey-Valueストアで、話がすむデータがいくつかあり、
現状のMySQLよりも速い方法があるのなら、ぜひ、試してみたいところです。

そこで、今回、hiroshiが見つけてきたredisがよさそうなので、「そもそも本当に速いの?」というのを、簡単なベンチマークを取って、試してみました。

このベンチマークの環境は、DECOLOGで使用しているものがベースになっています。
そのため、ツッコミどころはたくさんあると思いますが、

「DECOLOGの環境では、こういう結果でした」


というご紹介だという前提で、読み進めてください。


1. ベンチマークの環境


サーバーは、4台用意しました。
サーバーのハードウェアは、すべて同じで、
CPUIntel Xeon L5410 × 2
Mem12GBytes
HDD685G(RAID1)
Net100Mbps
という構成です。

サーバーA

ベンチーマークを取るサーバー
このサーバー上で、abを走らせます

サーバーB

Apache + PHPのサーバー
DECOLOGで、実際にサービスしているWebサーバーと
同じセットアップをしてあります。
関係ありそうなソフトのバージョンを上げておくと。。。
Apache
2.2.x(MaxClients 200)
PHP
5.2.x(APC 3.0.x)
MySQLへの接続
PEAR::DB
Redisへの接続1
owlient-phpredis-2.0.4-5
Redisへの接続2
Rediska0.5.0
と、なっています。

サーバーC

MySQLサーバー
バージョン: 5.0.x
ストレージは、InnoDB、BlackHole、Archiveを使用しました。
InnoDBのパラメーターのうち、スピードに関係ありそうなモノのは、
こんな↓感じで設定しています。
innodb_buffer_pool_size=9216M
innodb_flush_log_at_trx_commit=2
innodb_file_per_table

サーバーD

Redisサーバー
バージョン: 2.0.1
パフォーマンスに関係しそうな設定は、こんな↓ところでしょうか?
save 900 1
save 300 10
save 60 10000
appendonly no
vm-enabled no

2.ベンチマークの方法


サーバーAから、abコマンドで、
$ ab -c 200 -n 100000 http://server-b/path/to/benchmark/script.php
として、abの出力のうち、
Requests per second
という項目に注目しました。

また、事前に、MySQL、Redisともに12万件程度の、id(int) => value(int)という形式の
データを事前にストアしてあります。

3. テスト項目

3.1 インクリメントのテスト

idをキーにして、valueをインクリメントする、というのをテストしました。

SQLにすると、こんな↓感じです。
update counter set count_value=count_value+1 where id=?
Redisなら、incrコマンドですね。

3.2 insertのテスト

現在、Archiveエンジンでロギング+バッチで集計、としている部分を、
redisのincrで置き換えられないか?というのも試してみたかったので、
一緒にベンチマークを取ってみました。

4. PHPのredisインターフェースについて


redisのプロジェクトホームへ行くと、
Predis、Rediska、redis.php、phpredisの順で、PHPのインターフェースが記載されています。
Rediskaは、PHPのみで記述されていること、phpredisは、PECLのmemcacheに使用感が似ていたこと、
からこの2つを取り上げました。

5. ベンチマークの結果


さて、前置きはコレぐらいにして、ベンチマークの結果です。
それぞれ、5回試行して、最大/最小値をカット、中間値の3つの値の平均を取っています。

で、結果は、こんな↓感じでした。
MySQL
コマンドストレージreq/sec
updateBlackHole3650.94
updateInnoDB3204.03
insertBlackHole3400.94
insertArchive3435.64

Redis
コマンドクライアントreq/sec
incrphpredis6553.42
incrRediska2955.51


ついでに、select/getも各々1パターンだけとってみました。
エンジンreq/sec
MySQL(InnoDB)3699.17
redis(phpredis)6317.66

それぞれをグラフにするとこんな感じです。
図.コマンド/ストレージ


図.コマンド/クライアント




図.エンジン

6.感想


このベンチマークの結果、DECOLOGの環境では(←ここ、大事です)、redis+phpredisが頭抜けて速いことがわかりました。

また、ベンチマークを取っていたときは、
「すげーっ!!redis、速ぇーーーっ!!」と興奮していたのですが、
少し間を置いてから、冷静になって考えてみると、
・phpredisとRediskaの結果の対比
・RediskaとMySQLがほぼ変わらない
を考えると、PHPのコードが多分に影響してるように思えます。
MySQLの接続は、DECOLOGの歴史的な要因で、PEAR::DBですし。。。

が、「現状のDECOLOGの環境」をベースに考えれば、
やっぱり、redis+phpredisが断然速いので、redisをサービスへの投入することを決めました。
新しい要素の投入は、結構、この程度のノリでやってます。
実際にサービス投入/運用してみて、初めて見えてくる問題とかありますし。。。

7. サービスに投入してみたけれど。。。


この記事を書いてる時点で、redisをサービスに投入して、
うまく行った事例が1つと、うまく行かなかった事例が1つあります。

うまく行かなかった事例では、問題が2つ発生しました。
1つはパラメーターの調整で解決できたのですが、
もう1つの問題は解決できずに、サイトへのアクセスに影響が出るトラブルになってしまったので、
MySQLに戻しました。

うまくいった事例では、本当にスムースに、期待通りに稼働してくれています。
サーバーのロードアベレージもMySQLに比べて低めで推移してますね。

redisのサービスへの投入方法や、うまくいかなかった事例については、
次回以降に、ご紹介しようと考えています。

では、また次回に♪