「NoSQL」という言葉を、最近知りました。
確かに、データベースをテーブルごとに小分けして行くと、トランザクションとか、SQLのjoinとか使わなくなって、DECOLOGでも、MySQLを単純なKey-Valueストア的な使い方をしている箇所がいくつかあります。
Key-Valueストアと言えば、DECOLOGでもmemcachedを使用していますが、memcachedのスピード感でデータが揮発しないというのは非常に魅力的です。
DECOLOGのデータ群の中でも、簡単なKey-Valueストアで、話がすむデータがいくつかあり、
現状のMySQLよりも速い方法があるのなら、ぜひ、試してみたいところです。
そこで、今回、hiroshiが見つけてきたredisがよさそうなので、「そもそも本当に速いの?」というのを、簡単なベンチマークを取って、試してみました。
このベンチマークの環境は、DECOLOGで使用しているものがベースになっています。
そのため、ツッコミどころはたくさんあると思いますが、
「DECOLOGの環境では、こういう結果でした」
というご紹介だという前提で、読み進めてください。
1. ベンチマークの環境
サーバーは、4台用意しました。
サーバーのハードウェアは、すべて同じで、
CPU | Intel Xeon L5410 × 2 |
Mem | 12GBytes |
HDD | 685G(RAID1) |
Net | 100Mbps |
サーバー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 |
update | BlackHole | 3650.94 |
update | InnoDB | 3204.03 |
insert | BlackHole | 3400.94 |
insert | Archive | 3435.64 |
Redis | ||
コマンド | クライアント | req/sec |
incr | phpredis | 6553.42 |
incr | Rediska | 2955.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のサービスへの投入方法や、うまくいかなかった事例については、
次回以降に、ご紹介しようと考えています。
では、また次回に♪