-
redisとnode.js
対象読者
- node.js/npmはインストール済み
- macなどの*nixを持っている
- redisはよくわからない

redisのいいところ
- 小さい! 持ち運びしやすい! 良い意味で何もない!
- 純粋KVSより少し豊かなほどよい甘み
- 簡素ですので、パフォーマンスなどに関して色々「狙いやすい」
- あの、express作者さんもよく使ってらっしゃいますよ
僕みたいなコンシューマーゲーム難民に是非オススメしたい、組み込み系の薫りとwebっ子っぽいカジュアルな感覚が同居したシンプルDBとなっております。
redis本体
ダウンロードページから最新版(この文章を書いている時点では2.4.4)をダウンロードして、下記のように一行makeと打てば終わりです。
make続けてインストールするか否かはお任せします。この段階で、「展開ディレクトリ/src/redis-server」がありますので、起動しておきます。これで、redisの利用準備完了です。redisがさっぱりという方はここで、「展開ディレクトリ/src/redis-cli」を使って、実際に動作を試されることをおすすめします。
node_redis
client一覧にあるように、node.jsのredisクライアントは「node_redis」に星がついています。これが標準っぽいので、これを使いましょう。いつのものように、
npm install redisで、okです。
hiredis
上記node_redisのgithubページに行くといきなりhiredisというのが現れますが学習当初は不要だと思います。hiredisはredisの応答をパースする高速ネイティブライブラリでなくても動きます。もちろん、
npm install hiredisで、さっくりインストールできるので、使わない手はないのですが。
examples!
準備はできたので、公式チュートリアルを眺めたり、ここなんかをいじったり、走らせたりすると、それほど苦もなくnode_redisはわかると思います。あ、redis超入門は基本的にこれで終わりです。redisコマンド自体は単純ですからね。
よく引っかかるポイント
ここで、僕が当初引っかかったポイントを纏めます。
- redisの公式ドキュメントは実はreplになっているので、redisを立ち上げたり、インストールすること無く、ブラウザだけでredisの学習ができる(下図参照)
- 実はget/setの2コマンドだけで、大体KVSとして使えてしまう
- 実はJSON.stringify/parseを組み合わせて文字列を投入すれば、結構複雑なデータもredisに任せられる
- その他、色々あるコマンドやデータ型は複数のプロセス間で連携するためにあるだけなので、redisに慣れるまで放置でも問題なし

個人的には特に3.が盲点でした。これに気づいて、あ、もうこれで大体大丈夫じゃん、ということで、何でもredisにお願いする流れになってしまいました。
ざっと、こんなもんです。ええっと、それから、実際にredisとつきあいはじめると単純なコマンドの動きではない所が気になり始めますので、それについて、下記でまとめたいと思います。
中身
redis本体/node_redisともに、それほどドキュメントがありませんので、ハックが欠かせません。逆に、ハックがしやすい簡素なシステムであることがredisの良さだとも思うのですが。
というわけで、ハックのお役立ち情報をまとめます。
仕組みがわかれば怖くない
ちょっと、commands.jsを御覧ください。ここにはredisのコマンド名が列挙されております。コマンド「名」だけです。はい。実際にredis.get/setのようにredisクライアントのメンバ関数としてアクセスする関数は全てこの配列から生成されております。
実は、redisの通信プロトコルは極めて簡素でして、コマンド名と引数が決まったら、その実装は大体共通みたいなんです。というわけで、ここらへんにある、
commands.forEach(function (command) { RedisClient.prototype[command] = function (args, callback) { if (Array.isArray(args) && typeof callback === "function") { return this.send_command(command, args, callback); } else { return this.send_command(command, to_array(arguments)); } }; RedisClient.prototype[command.toUpperCase()] = RedisClient.prototype[command]; Multi.prototype[command] = function () { this.queue.push([command].concat(to_array(arguments))); return this; }; Multi.prototype[command.toUpperCase()] = Multi.prototype[command]; });を見ていただければわかるように、すべての関数がcommandsからsend_command関数を使って生成されています。要するに、node_redisの関数はほとんどsend_commandなんです。ですから、node_redisで困ったことが起きたり、挙動を確認したいということになったら、
- 通信開始/終了までの流れをよく確認する(認証とか、ここは色々罠がある)
- send_commandの動きを確認する
の、2つでほとんど解決できます。
nodeだからpiplining!
redis高速化の肝として、ある時期からpipeliningが推奨され始めました。要するに応答を待たずにコマンドを送りまくろうというものです。これ、他の言語なら結構大変(java版クライアントのjedisを少し眺めたことがありますが、パイプライン処理用に手のこんだことをしているみたいです)なのですがnode.jsなら、デフォでpipeliningです。非同期IOのnodeですから、そもそも待ちません。むしろ、nodeに慣れ親しんだ方なら、redis本家のpipelinineの文章が何を言いたいのか当たり前すぎて分からないかもしれません。こんなコードを見てもらえるとpipeliningと非pipelining(=通常)の違いがわかってもらえるのではないでしょうか。
// 非pipelining = redis的に普通の処理 redis.incr('x', function() { redis.incr('x', function() { redis.incr('x', function() { redis.incr('x', function() { //hoge }); }); }); }); }); // redis的なpipelining redis.incr('x', function() {}); // この場合コールバックは不要ですがなんとなく書きました redis.incr('x', function() {}); redis.incr('x', function() {}); redis.incr('x', function() {//hoge});pipeliningと非pipeliningの書き分けがとても自然です。時代はnode.jsであることをここらへんでも感じさせてくれますね。ただ、今後計画されているredis clusterなどによってDB処理待ちの仕方が影響を受けると思われる(僕の脳内では……)ので、その点はご注意を。
まだまだredisがわからない!
意外にredisのソースをハックすると楽に答えにたどり着ける場合があります。例えば、僕はreplicationについて疑問に思ったことがあったのですが、なかなかドキュメントが見つかりませんでした。あるのかもしれませんが、僕の英語力では無理でした。でも、grepしたらあっさり。replication.cなんてまんまなファイルの冒頭にあり、grepを何回かしたらなんとなくわかりました。redisのソースは読みやすいです。そこらへんの作者さんの思いというのはここらへんで読めます。
unit test時の注意点
おまけです。テスト時に個人的にはまった点を残しておきます。みなさんも、お忘れなく。
- redisClient.on(‘ready’)で待ちましょう
- クライアントを作っては捨てることを繰り返す場合はend()を
- クライアントを使いまわすというやり方もあります
ちなみに僕はredisのmockを自作して、ほとんどそれで済ませています。
さて、次の方……
い、いなくね? う、見落としてるだけかなあ。誰かー。誰かー。
12月 18, 2011に公開 with 11リアクション
-
christinaertがこの投稿を「スキ!」と言っています
-
botanically96がこの投稿を「スキ!」と言っています
-
security980dekがこの投稿を「スキ!」と言っています
-
giveaway69bopがこの投稿を「スキ!」と言っています
-
emileeyou89がこの投稿を「スキ!」と言っています
-
takuyanがsanami-mikioからリブログしました
-
bonham690がこの投稿を「スキ!」と言っています
-
dakeshiがsanami-mikioからリブログしました
-
sanami-mikioの投稿です