1. ホーム
  2. caching

[解決済み】Redisは単なるキャッシュなのか?

2022-04-02 04:21:57

質問

Redisのドキュメントをいくつか読み、以下のチュートリアルを試してみました。 http://try.redis-db.com/ . 今のところ、RedisとVelocityやEnterprise Library Caching Frameworkのようなキャッシュ技術との間に違いは見当たりません。

事実上、一意のキーを使ってインメモリデータストアにオブジェクトを追加しているだけです。リレーショナルなセマンティクスはないように見えますが......。

何が足りないのでしょうか?

解決方法は?

いいえ、Redisはキャッシュ以上のものです。

キャッシュと同様に、Redisはkey=valueのペアを保存します。しかし、キャッシュとは異なり、Redisは値に対して操作を行うことができます。Redisには、文字列、セット、ハッシュ、リスト、ソートされたセットという5つのデータ型があります。それぞれのデータ型には様々な操作が用意されています。

Redisを理解する最良の方法は、データベースに格納する方法を考えずに、アプリケーションをモデル化することです。

例えば、StackOverflow.comを作りたいとします。シンプルにするために、質問、回答、タグ、そしてユーザーが必要です。

質問、ユーザー、回答のモデル化

各オブジェクトはMapとしてモデル化することができる。例えば、質問は、{id, title, date_asked, votes, asked_by, status}のフィールドを持つマップです。同様に、回答は{id, question_id, answer_text, answered_by, votes, status}のフィールドを持つマップです。同様に、ユーザーオブジェクトをモデル化することができます。

これらのオブジェクトは、それぞれHashとして直接Redisに保存することができます。一意なidを生成するには、atomic incrementコマンドを使用します。次のようなものです。

$ HINCRBY unique_ids question 1
(integer) 1
$ HMSET question:1 title "Is Redis just a cache?" asked_by 12 votes 0
OK

$ HINCRBY unique_ids answer 1
(integer) 1
$ HMSET answer:1 question_id 1 answer_text "No, its a lot more" answered_by 15 votes 1
OK

アップボーティングの取り扱い

さて、誰かが質問や回答に対してアップボートをするたびに、次のことを行う必要があります。

$ HINCRBY question:1 votes 1
(integer) 1
$ HINCRBY question:1 votes 1
(integer) 2

ホームページの質問一覧

次に、ホームページに表示する直近の質問を保存したいと思います。.NETやJavaのプログラムを書いているのであれば、質問をListに保存するでしょう。これはRedisでこれを保存する最良の方法であることが判明しました。

誰かが質問するたびに、そのidをリストに追加します。

$ lpush questions question:1
(integer) 1
$ lpush questions question:2
(integer) 1

さて、ホームページをレンダリングしたいとき、Redisに直近の25問を問い合わせます。

$ lrange questions 0 24
1) "question:100"
2) "question:99"
3) "question:98"
4) "question:97"
5) "question:96"
...
25) "question:76"

IDが取得できたので、パイプラインを使ってRedisからアイテムを取得し、ユーザーに表示します。

タグによる質問、投票数による並べ替え

次に、各タグの質問を取得したいと思います。しかし、SOはそれぞれのタグの下でトップ投票された質問、新しい質問、未回答の質問を見ることができます。

これをモデル化するために、RedisのSorted Set機能を利用します。Sorted Setでは、各要素にスコアを関連付けることができます。そして、そのスコアに基づいて要素を取得することができます。

では、Redisタグでこれをやってみましょう。

$ zadd questions_by_votes_tagged:redis 2 question:1 
(integer) 1
$ zadd questions_by_votes_tagged:redis 10 question:2 
(integer) 1
$ zadd questions_by_votes_tagged:redis 5 question:613 
(integer) 1
$ zrange questions_by_votes_tagged:redis 0 5 
1) "question:1"
2) "question:613"
3) "question:2"
$ zrevrange questions_by_votes_tagged:redis 0 5 
1) "question:2"
2) "question:613"
3) "question:1"

こっちは何をしたんだ?私たちは質問をソートされたセットに追加し、各質問にスコア(投票数)を関連付けました。質問がupvotedされるたびに、私たちはそのスコアを増やします。そして、ユーザーが"Questions tagged Redis, sorted by votes"をクリックすると、私たちは単に zrevrange で、上位の質問を取得します。

ページを更新することなくリアルタイムに質問

そして最後に、ボーナス機能です。質問ページを開いておくと、新しい質問が追加されたときにSOが通知してくれます。ここでRedisはどのように役立つのでしょうか?

Redisはpub-subモデルを持っています。例えば、"channel_questions_tagged_redis"のようなチャンネルを作ることができます。そして subscribe のユーザを特定のチャンネルに招待します。新しい質問が追加されたとき、あなたは publish をそのチャンネルに送信します。そうすると、すべてのユーザーがそのメッセージを受け取ることになります。ブラウザに実際にメッセージを届けるには、ウェブソケットやコメットなどのウェブ技術を使う必要がありますが、Redisはサーバサイドのすべての配管を助けてくれます。

永続性、信頼性など

キャッシュと異なり、Redisはハードディスク上にデータを永続化します。信頼性を高めるためにマスターとスレーブを設定することができます。詳しくは、こちらの永続化とレプリケーションをご覧ください。 http://redis.io/documentation