2010-04-20

[翻訳]rediscookbook/4_higher_level_data_structures/implement_a_social_graph

### 問題

ある種のアプリケーションでユーザのソーシャルグラフを実装するのに単一または複数の方向の関係が利用可能な状態(フォローやフレンドシップ)で Redis を使いたいとしましょう。

### 解法

Redis 組み込みの set 関数を使って、各ユーザのユニークID をキーとした「follow」、「follower」と「blocked」リストを構成してください。redis の生データではこのように見えます:

    redis> SADD user:1:follows 2
    (integer) 1
    redis> SADD user:2:followers 1
    (integer) 1
    redis> SADD user:3:follows 1
    (integer) 1
    redis> SADD user:1:followers 3
    (integer) 1
    redis> SADD user:1:follows 3
    (integer) 1
    redis> SADD user:3:followers 1
    (integer) 1
    redis> SINTER user:1:follows user:1:followers
    1. 3

### 検討

Redis はキーに割り当てられたユニークな値の集まりの「sets」を構成することができます。
特定のユーザのために「follows」「followers」リストの両方を作成し、簡単なセットの交点を使用することで彼らの「friendships」について求められるでしょう。

Ruby でそのシステムを実装する場合には、このように見えます。:

{% code_snippet social_graph.rb %}

2010-04-14

rediscookbook翻訳中です。

最近めっきりご無沙汰の Redis 絡みで、
先日公開されていた RedisCookbook
リハビリがてら、いつものなんちゃって日本語訳中です。
(一部動作未確認)

本当は githubのリポジトリ に公開したいのですが、
push 時のエラーが解決できなく、時間切れ中。
(リポジトリ作った後の手順で README は push できたのですが。)

懐に温めててもしかたがないので、ブログに公開することにしました。
(チェンジセット:5c5816b312bf33adc429ac45633b4c61c4fa9cef までのrecipe.md)
(11日の最後のチェンジセット以降は未確認)
(チェンジセット:57216e1 に合わせて修正)

■構成


[翻訳]rediscookbook/README.md

# Redis クックブック

### みんなの知識で Redis コミュニティを育てましょう!

この Redis Cookbook にみんなのパターンやメソッドのアイデアを持ち寄りましょう。

- - -

### レシピに貢献する方法

1. このリポジトリを Fork して新しいトピックのブランチ(フォルダ)を作成してください。
2. メタデータ(著者やタグ)を含んだ YAML ファイルを作成したフォルダに追加してください。
3. pull request を送ってください。-- 新規や追加したレシピの簡単な紹介を含めてください。
4. ドキドキしましょう。

### もっと貢献する方法

下記のことが可能です:
* 既存のレシピにプログラム言語に寄らずサンプルコードを追加すること。リポジトリを Fork して関連ディレクトリにコードを追加してください!
* rediscookbook.org ウェブサイトを訪れてください。このサイトはオープンソースで `site` フォルダに丸ごと入っています。
* 誤字、書式誤り、リンク切れ、その他小さなことを見つけてください。 どんな潜在的な改良でも「小さすぎる」ということはありません。-- とにかくフォークしてください。


### 主催者

* [Tim Lossen](http://github.com/tlossen)
* [Ted Nyman](http://github.com/tnm)

### ライセンス

Creative Commons Attribution Share Alike 3.0

[翻訳]rediscookbook/IDEAS

ウェブチャットの作成方法 (Pieter Noordhuis) ?
http://gist.github.com/348262

現在オンラインのユーザをトラックする方法 (Luke Melia) ?
http://www.lukemelia.com/blog/archives/2010/01/17/redis-in-practice-whos-online/

分散ロックの実装方法 (amix)
http://amix.dk/blog/post/19386

twitter クローンを書く方法 (Daniel Lucraft) ?
http://github.com/danlucraft/retwis-rb

Node.js によるユーザの位置情報をトラックする方法 (Rick Olson)
http://techno-weenie.net/2010/2/3/where-s-waldo-track-user-locations-with-node-js-and-redis

stats を組み込みで使う方法 (Ben O'Steen)
http://oxfordrepo.blogspot.com/2010/01/usage-stats-and-redis.html

クラウドを利用した文書解析方法 (Simon Willison)
http://simonwillison.net/2009/Dec/20/crowdsourcing/

短縮 URL サービスの構築方法 (Sunil Arora) ?
http://sunilarora.org/url-shortener-service-using-redis

メモ化の方法 (Levi Cook)
http://github.com/levicook/memodis

redis の内容を点検する方法 (Chris Kite)
http://github.com/chriskite/rediscover

大量のアトミックな操作を発生させる方法 (Nate Wiger)
http://github.com/nateware/redis-objects

boogle クローンを書く方法 (Nick Quaranto)
http://github.com/qrush/beesknees

[翻訳]rediscookbook/5_durability_and_consistency/make_data_more_durable

### 問題

Redis にあるデータの耐久性を上げたい。

### 解法

Redis 組み込みのbuilt-in *追記型ファイル* (AOF) を使用してください。

`redis.conf` という Redis 構成ファイルを編集して、次の行を含めてください:
    appendonly yes

Redis はすべてのコマンドを AOF に対応させる予定です。
もしサーバがクラッシュしてもこのファイルから状態の再構築ができるでしょう。
MySQL の binlog など、他のデータベースで一般的なログファイルととてもよく似た振舞いをします。

### 検討

AOF 自身は構成可能です。 耐久性と速度のトレードオフを特徴とする3つの異なるオプションがあります。
`redis.conf` にこれら構成を設定できます。

3つのコマンドとは、すべてのコマンドで強制的に同期する、1秒毎に同期する、同期しない(つまりオペレーティングシステムのプロセスに任せる)です。Redis のデフォルトはすべてのコマンドで同期するですが、とても遅くなるでしょう。通常、2番目のオプションは安全性(訳注:耐久性?)と速度とのトレードオフです。

### 参照

[翻訳]rediscookbook/4_higher_level_data_structures/implement_a_fifo_queue

### 問題

基本的な push と pop 操作でシンプルな抽象化された先入れ、先出しのキューを実装して Redis を使いたい。

### 解法

Redis 組み込みの `List` データ型は自然なキューです。事実、単なるキューの実装で、`List` 操作の限定されたセットを便利にする必要があります。

    redis> LPUSH queue1 tom
    (integer) 1
    redis> LPUSH queue1 dick
    (integer) 2
    redis> LPUSH queue1 harry
    (integer) 3
    redis> RPOP queue1
    tom
    redis> RPOP queue1
    dick
    redis> RPOP queue1
    harry


### 検討

Redis は *ブロッキングポップ*操作と同等の4つの基本的なリストプッシュとポップ操作(RPUSH, LPUSH, LPOP, RPOP)が提供されています。これらはすべて O(1) オーダで、コマンドの時間的コストはリストの長さに依存しません。

Redis コマンド上で簡単なキューを実装するには、簡単で、さらっと Redis の力を把握するには良いイントロです。

例えば、ここに、オブジェクトレベルの相互作用(新しいキューの ID を一意にするために INCR を使います)を提供する Python キューがあります。:

    r = redis.Redis()

    class Queue(object):
        """抽象 FIFO キュー"""
        def __init__(self):
            local_id = r.incr("queue_space")
            id_name = "queue:%s" %(local_id)
            self.id_name = id_name

    def push(self, element):
        """キューの最後に要素を Push する"""
            id_name = self.id_name
            push_element = redis.lpush(id_name, element)

    def pop(self):
        """キューの最初の要素を Pop する。"""
            id_name = self.id_name
            popped_element = redis.rpop(id_name)
            return popped_element


### 参照

[翻訳]rediscookbook/3_object_level_interaction/using_a_ruby_library_to_store_objects

### 問題

Ruby オブジェクトを永続化する [remodel](http://github.com/tlossen/remodel) を使いたい。

### 解法

オプションを探し、1つ選んでください! Ruby には オブジェクトを保存するいくつかの永続化ライブラリがあります続化オブジェクトが存在しています。
このレシピでは、例として [Ohm](http://github.com/soveran/ohm) と [remodel](http://github.com/tlossen/remodel) を取り上げます。
しかし、読者はこの目的のために使用できる他の良いライブラリがあることを忘れないでください。
[どうか、他のライブラリやたくさんの使用例を追加してください。]

一般的な抽象化戦略は複雑なスキーマ定義無しでオブジェクトをマッピングすることで、
同等の結果を得るためにとても簡単なドメイン固有言語を使用しています。

次に Ohm の例を考えてください。
ここでは、3つの任意のオブジェクト(Event, Venue, および Person)をモデル化し、Event にバリデーションを提供するつもりです。

{% code_snippet ohm.rb %}
Remodel は永続化エントリの説明的なシンプルな DSL を提供します。:
よく知られている 'has_many' 関連は remodel ではこうです。

{% code_snippet remodel.rb %}
もし上記を `cookbook.rb` として保存して、Redis をローカルで動かせるなら、
Ruby シェルを開いて、実行できます。

    >> require 'cookbook.rb'
    => true
    >> book = Cookbook.create :title => 'Python Cookbook', :author => 'Alex Martelli'
    => #
    >> recipe = book.recipes.create :name => 'Sorting a Dictionary'
    => #
    >> recipe.book
    => #

### 検討

永続化オブジェクトのために既存のライブラリを使う重要な理由は、
組み込みのbuilt-in *アサーション* や バリデーションの力です。
例えば Ohm では、数値のみフィールドには確かに数値にマッチするかをアサーションします。
`format` バリデーションのために正規表現を使うことが出来ます。:

    assert_format :username, /^\w+$/

Remodel はそれ自身「最小のオブジェクト-redis マッパー」として定義され、簡単なマッピング戦略に使います。:
オブジェクトのすべてのプロパティは JSON ハッシュにシリアライズされ、単一キー配下に保存されます。

関連の扱いは異なっており、専ら — で扱われます。
関連の両端は別々のキーに保存されます。
`has_many` は Redis list を使い、関連オブジェクトのキーを保存し、
`has_one` は Redis string を使い単一の関連キーを保存します。
この手法は、どんなオブジェクトでも(デ)シリアライズすること無く、関連を変更できるという利点があります。

### 参照





----
追記
チェンジセット(57216e1)に合わせて変更

[翻訳]rediscookbook/3_object_level_interaction/introduction_to_storing_objects

### 問題

任意の Ruby オブジェクトを Redis に保存したい。

### 解法

どんなキー/値データベースでも、構造化するのにキーを使えます。:
ここでは Ruby を使った例ですが、原則どんなプログラミング言語でも利用できます。

    >> redis.set "event:42:name", "Redis Meetup"
    => "OK"

    >> redis.get "event:42:name"
    => "Redis Meetup"

同じ例ですが、今回はまず固有の ID を生成しています。:

    >> id = redis.incr "event"
    => 1

    >> redis.set "event:#{id}:name", "Redis Meetup"
    => "OK"

    >> redis.get "event:#{id}:name"
    => "Redis Meetup"

別解は、保存するときにデータをシリアライズして、検索するときにデコードすることです。:

    >> id = redis.incr "event"
    => 2

    >> redis.set "event:#{id}", {:name => "Redis Meetup"}.to_json
    => "OK"

    >> JSON.parse redis.get("event:#{id}")
    => {"name" => "Redis Meetup"}

最新バージョンの Redis で利用可能なもう1つの解は、新しいデータ Hash 型を使うことです。:

    >> id = redis.incr "event"
    => 3

    >> redis.hset "event:#{id}", "name", "Redis Meetup"
    => "OK"

    >> redis.hget "event:#{id}", "name"
    => "Redis Meetup"

お分かりのように、Redis は非常に柔軟で、情報を保存する最も良い戦略を決められます。

オブジェクト属性に基づくキー生成を自動化するいくつかのライブラリがあります。これらをチェックして使い方を学んでください。

* [DataMapper Adapter](http://github.com/whoahbot/dm-redis-adapter)
* [Ohm](http://ohm.keyvalue.org)
* [Redis Model](http://github.com/voloko/redis-model)
* [Redis Objects](http://github.com/nateware/redis-objects)
* [Remodel](http://github.com/tlossen/remodel)

### 参照

いろいろなライブラリを使った戦略のRuby のオプションを確認するには
 **オブジェクトを保存するために Ruby ライブラリを使う** をチェックアウトしてください。

[翻訳]rediscookbook/2_basic_commands/pipeline_multiple_commands

### 問題

単一のアトミックコマンドを使って、いくつかの Redis コマンドを実行したい。

### 解法

コマンドのキューを作成し、それらをアトミックに実行するには MULTI/EXEC コマンドを使います。
キューの開始には `MULTI` コマンドを使います。Redis は `OK` を返します。
それから各コマンドのキューを作ってください。最終的には、`EXEC` を使用してコマンドを実行します。
Redis は各コマンド毎にか返値と一緒に multi-bulk を返します。
この基本的な例で、3つの値をリストに追加し、'country-count' と呼ばれるキーを(3に)増加させ、
それからリストのすべての値の範囲を求めます。

必要なら、MULTI キュー と既存のキューをクリアするために DISCARD コマンドを使うことができます。

    redis> MULTI
    OK
    redis> LPUSH country_list france
    QUEUED
    redis> LPUSH country_list italy
    QUEUED
    redis> LPUSH country_list germany
    QUEUED
    redis> INCRBY country_count 3
    QUEUED
    redis> LRANGE country_list 0 -1
    QUEUED
    redis> EXEC
    1. (integer) 1
    2. (integer) 2
    3. (integer) 3
    4. (integer) 3
    5.
     1. germany
     2. italy
     3. france
   

### 検討

MULTI/EXEC (Redis 2.0 で追加予定)は Redis の非常に重要なコンポーネントで、多く語るに値します。
これが何をするのか、そして何をしないのか知ることはとても重要です。

M/E は次に述べるような意味で、「アトミック」です。
キューが実行されている間、他のクライアントが全く Redis サーバにアクセスできません
-- このキューは単一操作として扱われます。これはデータの完全性にとって重要です。

M/E プロセスは、コマンドがキューに追加されるときはいつでも、
構文エラーがあるとすぐに構文エラーを報告しながら実行するよう設計されています。例えば:

    redis> MULTI
    OK
    redis> LPUSH country_list italy
    QUEUED
    redis> LPUSH country_list italy germany
    Wrong number of arguments for 'lpush'


さて、 M/E は完全な「トランザクション」を提供 *しません*
-- 少なくとも常識的な意味では。-- 「ロールバック」の機能を含んでいないからです。
以下のような状況を考えてください。
比較的大きな M/E キュー(例えば、200個のコマンド)を作成して、EXEC を実行します。
すべての溜め込まれたコマンドが実行される前に、
(おそらくメモリを使い果たして)コマンド #148 でサーバがクラッシュしたとしましょう。
はじめの 148 個のコマンドは本当に実行されますが、残りは実行されません。

実際は、M/E では、EXEC コマンドが実行される *前* (つまり、溜め込み中)は 'すべてか無しか' 操作だけなのです。
-- 実行中はそうではありません。

Redis は問題に対処する興味深い方法を提供します。:馴染み深い追加のみファイルです。
Redis の次バージョンでは、キューのコマンド群は EXEC コマンドが完全に成功したときに AOF に書かれるだけです。
このため、万一サーバが中途半端な EXEC 状態でクラッシュしても、前の pre-EXEC 状態に従って状態を再構築できます。


### 参照

[翻訳]rediscookbook/2_basic_commands/get_and_delete

### 問題

Redis からオブジェクトをアトミックに GET し、 DELETE したい。

### 解法

    success = RENAME key key:tmp
    if success
      value = GET key:tmp
      DELETE key:tmp
      return value
    end

using `redis-cli`:

    >> SET TOTO 1
    OK
    >> GET TOTO
    1
    >> RENAME TOTO TOTO:TMP
    OK
    >> GET TOTO:TMP
    1
    >> DEL TOTO:TMP
    (integer) 1
  
    >> GET TOTO
    (nil)
    >> RENAME TOTO TOTO:TMP
    (error) ERR no such key   
### 検討

これは、簡単な例ですが、有効にRedisのアトミックな特徴を利用しています。RENAME 関数は最初に呼ばれた場合、成功し、その後呼ばれる場合はキーが変更されたので失敗するでしょう。GET と DEL は RENAME 関数のおかげで他のクライアントが操作しているオブジェクトデータを参照するのを防ぎます。(??)

### 参照




----
追記:
チェンジセット(57216e1)に合わせて修正

[翻訳]rediscookbook/2_basic_commands/empty_the_database

### 問題

Redis に既に保存されたすべてのキー(と関連する値)を削除したい。

### 解法

Redis の FLUSHALL コマンドを使用してください。

    $redis-cli flushall
    OK

### 検討

### 参照

[翻訳]rediscookbook/2_basic_commands/create_unique_ids

### 問題

あなたは、任意のオブジェクトに重複しない固有の ID を提供したい。

### 解法

Redis 組み込みのアトミックな INCR 関数を利用してください。

    $redis-cli INCR
    (interger) 1

    $redis-cli INCR
    (interger) 2

    $redis-cli GET
    1
       
    $redis-cli GET
    2
   
### 検討

固有の ID を提供する INCR を使うことは Redis の中心概念の1つです。しばしば「主キー」スタイルとしてリレーショナルデータベースで使われてきた同等な機能の代わりに使用されます。

固有のID を使うより多くの例は *Redis における Ruby オブジェクトの保存* を参照してください。

### 参照

[翻訳]rediscookbook/1_install_configure/install_with_make

### 問題

Linux や OS X や Posix 互換のオペレーティングシステムに Redis をインストールしたい。

### 解法

Redis は文字通り「設定いらず」です。最新の Redis [stable release](http://code.google.com/p/redis/) をダウンロードしてください。
tar を解凍し新しいディレクトリにファイルを作り、`cd` でそのディレクトリに入ってください。それから `make` 。 Redis はすぐにインストールされでふぉるのて設定を使って構成されます。`./redis-server` を実行するとサーバが動き出し、目的は達成です。

### 検討

Salvatore Sanfilippo は Redis の作者で、「設定いらず」でインストールすることに強いこだわりがあります。実際、Redis は全く依存関係がありません。「サーバからダウンロードしてmake するまで」どれくらい時間がかかったか計ると、たった 34 秒でした。

### 参照

[翻訳]rediscookbook/1_install_configure/install_with_installer

### 問題

以下のことをしたい:

* Linux や OS X や Posix 互換のオペレーティングシステムに Redis をインストールする。
* 標準レイアウトを使った設定でバイナリを配置する。
* root にインストールしたい場合は /etc/{init.d,rc.d}/redis にシステムコントロールスクリプトがある。
* 1つ以上のリモートホストにインストールする。
* *1つ* のコマンドを使って、ローカルにインストール可能であること。

### 解法

[redis-installer](http://github.com/wayneeseguin/redis-installer/) を使ってください。

1. localhost にインストールします:

まずは、redis-installer をダウンロードまたはクローンします。:

    git clone git://github.com/wayneeseguin/redis-installer/

次に、単に Redis をインストールします。:

    bin/install-redis

2. **1つ** のコマンドで localhost にインストールします。

"怠けてるのではなく、賢いんです!"

    bash < <(curl http://github.com/wayneeseguin/redis-installer/raw/master/bin/install-redis)

3. 複数のリモートホストにインストールします

まず、下記から redis-installer をダウンロードまたはクローンします。:

    git clone git://github.com/wayneeseguin/redis-installer/

次に、1つ以上のリモートホストに Redis をインストールします。

    bin/install-redis-on-hosts hostname1 [hostname2 [hostname3 ...]]

### 検討

インストールと設定で気をつけることは、 root としてインストールするかか user としてするかで異なります。 root では、/usr/local/ に、 user では~/.redis/ にインストールされる。

解法2は単に Redis インストーラスクリプトをダウンロードして、`bash` に直接実行コマンドを送んでいるだけです。

### 参照