motacaplaのめう

日頃得られた知見と気付きをdumpするところ

忙しい人のためのRedisチュートリアル

この記事は何?

RedisConf19参加にあたり, Redisのdocsをしっかり読み込んだことがなかったため実施した. 量が多いため, 途中から要約だけ載せる.(疲れたので)

https://redis.io/

なお, 現時点でのlatest stableはRedis v5.0.4である.

commands

データ型はstring, bit, hash, list, set, sorted set, hyperloglog, streamと多種揃っている. 呼び出せるコマンドについては全てココにあるため, 今回は割愛する. 日本語のドキュメントだと, v2.0.3までの関数は以下にある. コマンドリファレンス — redis 2.0.3 documentation

stream type

v5.0.0から stream型エントリ のデータ管理方法が実装された. stream型は名前のとおり, 時系列データを扱うためのデータ型である. XADDやXRANGE, XDEL, XTRIMといった先頭にXのつくコマンドがstream用のコマンドとなっている. 例. XADDのdoc XADD – Redis

例えばXADDは, 同一keyに対して複数valuesを与える形で記述できる.

redis> XADD mystream * name Sara surname OConnor
"1553778517432-0"
redis> XRANGE mystream - +
1) 1) "1553778517432-0"
   2) 1) "name"
      2) "Sara"
      3) "surname"
      4) "OConnor"
redis> XADD mystream * field1 value1 field2 value2 field3 value3
redis> XRANGE mystream - +
1) 1) "1553778517432-0"
   2) 1) "name"
      2) "Sara"
      3) "surname"
      4) "OConnor"
2) 1) "1553778517433-0"
   2) 1) "field1"
      2) "value1"
      3) "field2"
      4) "value2"
      5) "field3"
      6) "value3"

value登録時に発行される文字列をstream IDと呼ぶ. 例えば上記の例では"1553778517432-0"が該当する. ご覧の通り, stream IDは[unix msecのタイムスタンプ]-[シーケンス番号]と構成される.

以下参考.

qiita.com qiita.com streamのintroduction (とは思えない程の分量と内容) Redis Pub/Subを先に読むことを推奨 Introduction to Redis Streams – Redis

Pipelining

https://redis.io/topics/pipelining

TL;DR

ClientがRequestを発行してからServerがResponseし, Clientへ結果が戻るまでの時間をRoundTripTimeと呼ぶ. Server側がRequestを受信する度にResponseを返すのではなく, まとめて返事することで(server側の)system callsの実行回数が減り, レイテンシ低減する. それだけでなく, 時間辺りに実行できるクエリ数も増加する. できるだけpipeliningを使おう!←結論

Pub/Sub

https://redis.io/topics/pubsub

Apache Kafkaとか有名なやつ, メッセージングパターン.

TL;DR

例えばclientがsubscribeしたいとする. この時, clientはチャンネルをSUBSCRIBEコマンドで指定する. そしてチャンネルにpushされたメッセージは, それをsubscribeしている全clientに送信される. pushするにはPUBLISHコマンドを用いる. チャンネルのsubscribeをやめる場合は, UNSUBSCRIBEコマンドを用いる. Redis Pub/SubはパターンマッチングによるPub/Sub機能もある. それぞれPSUBSCRIBE, PUNSUBSCRIBEを使う. Pub/Sub subsystemの状態を見たい場合はPUBSUBコマンドを叩く.

以下参考.

Redisのpub/sub機能 - Qiita

Lua scripting

https://redis.io/commands/eval Luaスクリプトを実行できるよ!

> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
1) "key1"
2) "key2"
3) "first"
4) "second"

RedisとLuaの相互型変換は可能らしい. ただし, 浮動小数で返してほしい場合はLua側が文字列として返す必要あり.

If you want to return a float from Lua you should return it as a string

あとSHA-1ハッシュ関数を使うEVALSHAコマンドもある.

transactions

トランザクションもあるよ. https://redis.io/topics/transactions

トランザクション — Redis Documentation (Japanese Translation)

トランザクション自体の説明は以下参考.

データベースさわったこと無い新人向けトランザクション入門 - Qiita

TL;DR

主にMULTI, EXEC, DISCARD, WATCHコマンドを使う.

> MULTI
OK
> INCR foo
QUEUED
> INCR bar
QUEUED
> EXEC
1) (integer) 1
2) (integer) 1

特徴として, コマンドがミスっていても, 実行可能なものは処理されてしまうという点には気をつけたい.

even when a command fails, all the other commands in the queue are processed

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
MULTI
+OK
SET a 3
abc
+QUEUED
LPOP a
+QUEUED
EXEC
*2
+OK
-ERR Operation against a key holding the wrong kind of value

ロールバックはサポートされていない. 理由は - シンタックスが間違ってるときしか失敗しないから - ロールバックしなくても問題ないぐらい速い (もう一度実行しろってことかな)

DISCARDコマンドでトランザクションのabortが可能

> SET foo 1
OK
> MULTI
OK
> INCR foo
QUEUED
> DISCARD
OK
> GET foo
"1"

WATCHコマンドを使うと, 楽観的なロックが実現できる. WATCHコマンドは check-and-set の振る舞いを提供する. つまりWATCHコマンドで監視しているkeyに変更が加わった場合, トランザクション全体を中止する.

persistence

Redis Persistence – Redis

Redisでは大きく2つの永続化オプションがある もちろん使わないことも可能だし, 片方だけ使うこともできるし, 組み合わせて使うことも可能. 求める永続化の性能に依存.

  • RDB: 指定時刻ごとにデータセットのスナップショットを取得する. もしくはコマンドを叩いて取得する. スナップショットはバックアップとしては完璧だが, redisに障害発生時のデータ損失可能性はそこまで低く出来ない.

  • AOF(= Append only log): 実行されたコマンドをログとして残す. 耐障害性はRDBより高いが, ファイルサイズが大きくなりがち.

Memory optimization

Redisをメモリ効率よく使うためのTips, まだ執筆途中とのこと. https://redis.io/topics/memory-optimization

TL;DR

メモリ効率の良いhashをできるだけ使いましょう

だいぶ端折りましたが, 疲れたので残りは次回!