SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

CoffeeScriptによるモダンなWebアプリケーション開発

CoffeeScriptベストプラクティス集
Node.jsアプリケーション編(3)

CoffeeScriptによるモダンなWebアプリケーション開発 第5回

Redisにアクセスする

 RedisはNoSQL(注1)の一種で、キーバリューストア(注2)に分類されるデータベースです。SQLでMySQLなどのリレーショナルデータベースにアクセスする場合と比べてRedisはデータの読み書きが非常に高速です。RedisではSQLは使えないものの、文字列、リスト(注3)、セット(注4)、ハッシュ(注5)、ソート済ハッシュ(注6)といったデータ型を扱うことができ、Pub/Subの機能もあります。すべてのデータをメモリ上に置くことによって高速化を実現しているため、総データサイズが大きくなりすぎないように注意する必要があります。memcached(注7)とは異なり、データをディスクに永続化することが可能で、またレプリケーションも手軽にできます。RedisはGitHubやFlickrなどの大規模なWebサイトでも使われています。

 MySQLは複雑なSQLによる問い合わせができる点が便利ですが、レコード数が多くなってくると速度面での遅さが目立ち、高速化のための対策が必要となってきます。そのような場合、頻繁にアクセスされる一部のデータをMySQLからRedisに移し替えることでアプリケーションの高速化を図ることができます。

注1:NoSQL

 従来のリレーショナルデータベースの構造にこだわらないデータベースの総称。SQLを主言語としないことが特徴。Redisの他にCassandra、Riak、MongoDBなどが挙げられる。

注2:キーバリューストア

 キーと値のペアでデータを保存するデータベース。リレーショナルデータベースとは違ってデータ同士は関係性を持たず、SQLで検索することもできない代わりに、読み書きが非常に高速。

注3:リスト

 文字列の配列。

注4:セット

 文字列の集合。同じ文字列は二度出現せず、配列のような要素の前後関係も存在しない。JavaScriptで例えると、値がすべてtrueとなるオブジェクトに相当する。

注5:ハッシュ

 JavaScriptのオブジェクトに相当する。フィールドと値の組み合わせ。

注6:ソート済ハッシュ

 文字列の集合でありセットと似ているが、各要素がスコアを持つ。スコアによって全体がソートされ、要素どうしの前後関係が生まれる。スコアは重複してもよいが、文字列は重複不可。

注7:memcached

 メモリ上ですべてのデータを管理するキーバリューストア。データの永続化機能は持たない。多くのWebサイトで使われている。

node_redisのインストール

 Node.jsからRedisにアクセスするにはnode_redis(MITライセンス)というモジュールを使います。node_redisをインストールするにはプロジェクトのディレクトリで次のコマンドを実行します。

$ npm install hiredis redis

node_redisの使い方

 主な使い方をリスト14に示します。Redisのコマンドがすべてメソッドとして使用でき、コールバック関数の仕組みもすべてのメソッドで共通となっています。

[リスト14]Redisの各操作
redis = require 'redis'
# 127.0.0.1の6379番ポートで稼働しているRedisサーバに接続する。
client = redis.createClient 6379, '127.0.0.1'

# Redisサーバに接続できなかった場合
client.on 'error', (err) ->
  console.log "Error: #{err}"

# すべてのデータを消去する。
client.flushall (err, result) ->
  throw err if err

## 基本操作
# key1にvalue1をセットする。
client.set "key1", "value1", (err, result) ->
  throw err if err

  # key1の値を取得する。
  client.get "key1", (err, value) ->
    throw err if err
    console.log "key1: #{value}"

    # key1を削除する。
    client.del "key1", (err, result) ->
      throw err if err

## ハッシュの操作
# user1のnameとcountryフィールドをセットする。
client.hmset "user1", "name", "山田太郎", "country", "日本", (err, result) ->
  throw err if err

  # user1のすべてのフィールドと値を取得する。
  client.hgetall "user1", (err, user) ->
    throw err if err
    console.log "名前: #{user.name}"
    console.log "国籍: #{user.country}"

## 数値のインクリメント
# visitorsの値に1を加える。該当するキーがなければ自動的に作成される。
client.incr "visitors", (err, result) ->
  throw err if err

  # visitorsの値を取得する。
  client.get "visitors", (err, count) ->
    throw err if err
    console.log "訪問者数: #{count}"

## リストの操作
# queueにitem1, item2を追加する。
client.rpush "queue", "item1", "item2", (err, result) ->
  throw err if err

  # queueの値をすべて取得する。
  client.lrange "queue", 0, -1, (err, items) ->
    throw err if err
    console.log "キュー: #{items.join ', '}"

    # queueを5秒後に削除する。
    client.expire "queue", 5, (err, result) ->
      throw err if err

## セットの操作
# usernamesにtaro, jiro, saburoを追加する。
client.sadd "usernames", "taro", "jiro", "saburo", (err, result) ->
  throw err if err

  # usernamesのメンバーをすべて取得する。
  client.smembers "usernames", (err, usernames) ->
    throw err if err
    console.log "ユーザ名: #{usernames.join ', '}"

## ソート済セットの操作
# scoresに値を追加する。スコア、キーの順で複数指定できる。
client.zadd "scores", 90, "太郎", 100, "二郎", (err, result) ->
  throw err if err
  # scoresにさらに値を追加する。
  client.zadd "scores", 80, "三郎", (err, result) ->
    throw err if err
    # scoresの最後尾の値を取得する。
    client.zrange "scores", -1, -1, "withscores", (err, result) ->
      throw err if err
      console.log "1位: #{result[0]}君 #{result[1]}点"

 Redisサーバへの接続を切断するにはclient.quit()を呼びます。

 また、Pub/Subによる配信と購読を行うにはリスト15のように記述します。

[リスト15]RedisでPub/Subを行う
redis = require 'redis'

# 同一のサーバに接続するクライアントを2つ作成
client1 = redis.createClient 6379, '127.0.0.1'
client2 = redis.createClient 6379, '127.0.0.1'

client1.on 'subscribe', (channel, count) ->
  # client1の購読開始処理が完了した (2)

  # client2からmychannelにメッセージを配信する
  client2.publish "mychannel", "Message 1"
  client2.publish "mychannel", "Message 2"
  client2.publish "mychannel", "Message 3"

msgs = 0  # client1が受信したメッセージ数

client1.on 'message', (channel, message) ->
  # client1がメッセージの配信を受けた (3)
  console.log "#{channel}: #{message}"
  if ++msgs is 3  # 3回メッセージを受信したら
    # client1の購読をやめる
    client1.unsubscribe()
    # Redisへの接続を切る
    client1.quit()
    client2.quit()

# client1がmychannelの購読を開始する (1)
client1.subscribe "mychannel"

 このリストでは(1)、(2)、(3)の順番でコードが実行されます。RedisはPub/Subをレプリケーションによってスケールアウトさせることも可能で、シンプルでありながら非常に応用の幅が広いソフトウェアです。

 

 次回も引き続き、CoffeeScriptでNode.jsアプリケーションを開発する際によく使われる実用的な開発手法を紹介します。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
CoffeeScriptによるモダンなWebアプリケーション開発連載記事一覧

もっと読む

この記事の著者

飯塚 直(イイヅカ ナオ)

1984年東京都生まれ。 高校時代に趣味でPerlやJavaを使ってプログラミングを始める。 慶応大学湘南藤沢キャンパス卒業後、共同通信社にてニュースサイトの開発などを担当。 その後、面白法人カヤックにてソーシャルゲームの開発などを手がける。 2012年現在、カヤックを退社し個人として活動し...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/6529 2012/05/02 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー