4
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Redisの全データ型に触れてみた。キャッシュだけじゃない Redis 再入門。

Redis に触れたことがある方は多いと思いますが、キャッシュとして使うケースが多いのではないでしょうか?
僕も「スケーリングもできるキャッシュ」くらいな理解でしたが、ランキングなんかにも使えるらしいと聞いており、再入門してみました。

環境構築、テストデータ

公式の Docker を使います。
https://hub.docker.com/_/redis

ドキュメントどおりに以下で起動します。

docker run --name some-redis -d redis redis-server --appendonly yes

redis-cli を使えるようにしておきます。

brew install redis

データを出し入れする

今回は基本に忠実に、redis-cli で Redis のサポートするデータ構造に触れてみます。

redis-cli を起動します。

redis-cli

Redis にはいくつかのデータ構造がありますので、それぞれ見ていきます。

文字列

シンプルに key, value を保持します。一番使われる用途はこれでしょう。
セッション ID をキーにユーザ情報を保持したり。

127.0.0.1:6379> SET user_id1 kaiba
OK
127.0.0.1:6379> get user_id1
"kaiba"
127.0.0.1:6379> SET user_id1 kaibadash
OK
127.0.0.1:6379> get user_id1
"kaibadash"
127.0.0.1:6379> SET user_id2 taro
OK
127.0.0.1:6379> SET user_id3 jiro
OK
127.0.0.1:6379> MGET user_id1 user_id2 user_id3
1) "kaibadash"
2) "taro"
3) "jiro"

一気に取得することもできるんですね。

リスト

リストです。先頭、末尾に対して追加、削除できます。

127.0.0.1:6379> RPUSH members kaiba
(integer) 1
127.0.0.1:6379> RPUSH members taro
(integer) 2
127.0.0.1:6379> RPUSH members jiro
(integer) 3
127.0.0.1:6379> LLEN members
(integer) 3
127.0.0.1:6379> LPOP members
"kaiba"
127.0.0.1:6379> RPOP members
"jiro"

キュー構造を表現したりするのに良さそうですね。
Sidekiq とか Redis を使いますが、きっとこれを使っていたんですね。

セット

順番がなく、重複を許さないデータ構造です。

127.0.0.1:6379> SADD users kaiba
(integer) 1
127.0.0.1:6379> SADD users taro
(integer) 1
127.0.0.1:6379> SADD users jiro
(integer) 1
127.0.0.1:6379> SADD users kaiba
(integer) 0 # すでにいるので追加されなかった
127.0.0.1:6379> SREM users kaiba
(integer) 1
127.0.0.1:6379> SREM users NONE
(integer) 0
127.0.0.1:6379> SREM users jiro
(integer) 1

ビンゴの当選者の管理のために、ダブルビンゴの人はカウントしない、とか良いかもしれませんね。
知らないと他のデータ構造で頑張ってしまうことも多そうですね。

ソート済みセット

スコア値に従ってソートされるセットです。

127.0.0.1:6379> ZADD ranking 80 kaiba
(integer) 1
127.0.0.1:6379> ZADD ranking 100 dekisugi
(integer) 1
127.0.0.1:6379> ZADD ranking 10 nobita
(integer) 1
127.0.0.1:6379> ZRANK ranking nobita
(integer) 0
127.0.0.1:6379> ZRANK ranking kaiba
(integer) 1
127.0.0.1:6379> ZRANK ranking dekisugi
(integer) 2

スコアの昇順のようですね。
スコアなので感覚的には降順にしてほしい気がしますが…

127.0.0.1:6379> ZREVRANK ranking dekisugi
(integer) 0
127.0.0.1:6379> ZREVRANK ranking nobita
(integer) 2

ちゃんと昇順でとることもできます。

127.0.0.1:6379> ZRANGE ranking 0 2
1) "nobita"
2) "kaiba"
3) "dekisugi"
127.0.0.1:6379> ZREVRANGE ranking 0 2
1) "dekisugi"
2) "kaiba"
3) "nobita"

リストで取得することもできます。
ランキングの完成じゃないか…!

ハッシュ

Key Value 形式のデータ構造です。
はて、そもそも Redis は Key Value 形式のデータストアでは?と混乱しますが、
例えば以下のようなデータを保持できます。

{
  "id": 1,
  "name": "kaiba",
  "tweet": "Hello!"
}
127.0.0.1:6379> HSET tweet1 name kaiba
(integer) 1
127.0.0.1:6379> HSET tweet1 id 1
(integer) 1
127.0.0.1:6379> HSET tweet1 tweet Hello!
(integer) 1
127.0.0.1:6379> HGET tweet1 tweet
"Hello!"
127.0.0.1:6379> HGET tweet1 name
"kaiba"

今までこれをしたい場合は json を文字列にして入れることが多かったのですが、文字列ではなく Key Value のオブジェクトとして挿入できるのは気持ちがいいですね。

向いていること

Redis は以下に向いていると感じました。

  • シンプルな KVS としてキャッシュに
  • SQL だとどうしても重たくなりがちなランキングに
  • キュー構造を表現したい

向いていないこと

  • Value 間に関係を持たせる
  • 不正なデータが入らないようにする(制約)
  • Value で検索したい

まとめ

僕はキャッシュとしてしか使ったことがありませんでしたが、いくつかのデータ構造を表現できることを知りました。
特にランキングはシンプルながら強力だと感じました。
シンプルでとっつきやすいのも良いですね。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
4
Help us understand the problem. What are the problem?