node.jsでRedisを使ってみる【実践編】
久しぶりの更新。
node.js + Redisでチャット作ろうとして挫折してました。orz
作ったもの
githubに置いておきました。
yussk/mychat · GitHub
動かし方
cloneして、redis起動して、依存モジュールをインストールすれば動きます。
$ git clone git@github.com:yussk/mychat.git // forkしてからcloneでもいいかもしれません ... $ redis-server // redis起動。別ウインドウでやるのがおすすめ ... $ cd mychat $ npm install // package.jsonから依存モジュールを持ってくる $ node app.js // チャット起動
これでブラウザを立ちあげて localhost:3000 にアクセスするとチャットできます。
使った技術とか
express3 + ejs
express2 + ejs のときはデフォルトでレイアウト機能をサポートしてたのに
express3になってから削除されたみたい。なぜ削除したし。
それで少し困ったけど express-partials ってモジュールを入れて解決しました。
publicclass/express-partials · GitHub
socket.io
チャットといえばリアルタイム。そんなことから使ってみたけど難しかった。
基本はonでイベントを購読して、emitでイベントを発火させるっていう
よくあるオブザーバパターンだけれど、socket.ioの仕様は奥深い。
Socket.IO: the cross-browser WebSocket for realtime apps.
Redis
もともとnode.jsとredisの相性はいいのはわかってましたが、
socket.ioとの相性も良かったんですね。
Redisで保持しているセッションデータをsocket.ioのコネクションでも
参照できるのは助かりました。
Redis
チャットの設計
どんなチャットを作るかをまず決めないといけませんでした。
研修の時にチャット作ったので、それをリファクタしつつ書くことにしました。
チャットの流れは以下の通りです。
- 名前を入力してログイン(パスワード認証は無し)
- チャット部屋を選択または新しい部屋を作成する(部屋名の入力あり)
- 部屋の中で発言する
- 部屋から退室すると 2 の画面に戻る(部屋に誰もいなかったら部屋を削除する)
- ログアウトして 1 に戻る
パスワード認証はないので、ログアウトは実質名前を変えたい時に使うくらいです。
Redisのキー設計
KVSのキー設計って未だに慣れません。
RDMSに親しんでいたら発想の転換が必要ですね。
- global:room:id
文字列型。値はインクリメントされる数値。
部屋名のハッシュを作る時に利用します。ハッシュを作る時に
このglobal:room:idを含めることで部屋名の重複が合ったとしても
一意の部屋を作ることができます。
- rooms
リスト型。値はroomId:roomNameという形式。
部屋のリストです。roomIdはglobal:room:idと入力された部屋名を
md5でハッシュした文字列になります。
これでどんなに長い部屋名を入力しても32文字に丸められます。
roomNameは入力された部屋名になります。
- room:name
ハッシュ型。field: roomId, value: roomName
roomsは部屋のリストを管理しているため、値にroomIdとroomNameが混在してます。
こちらのroom:nameはroomNameを管理しているハッシュなので、
roomIdがわかれば日本語の部屋名を取得出来ます。
- room:roomId:message
リスト型。値はJSONでname, message, date, timeを持つ。
部屋の中で発言されたメッセージを管理します。
キーのroomIdの部分にはハッシュ化された部屋IDが入ります。
e.g. "room:647df86355c1d46b4db50011875fe82e:message"