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