🦓

Redisを使ってみる

2023/09/04に公開

はじめに

最近Redisを勉強しているのでRedisについてまとめてみました。

https://redis.io/

環境

Rails 7.0.7
ruby 3.2.1

Redisとは

Redis(Remote Dictionary Server)は、キー-値データベースおよびキャッシュシステムです。

Redisとリレーショナルデータベースの違い

1. テーブルという構造を持たない
→ データをキーと値のペアとして格納されるだけでなく、セット、リスト、ハッシュ、ソート済みセット、ビットマップなども操作できます。異なる用途に適したデータの格納と処理が可能です。
2. インメモリデータベース
→ データはメモリ内に格納されます。データの永続化を目的とする場合は向いていません。
3. スキーマレスデータベース
→ 固定のスキーマを持たない、新しいデータフィールドを動的に追加でき、データ構造を自在に変更できます。
4. パーフォマンス
→ インメモリデータベースであるため、高速な読み書きアクセスが可能です。しかし、データはメモリに収まる必要があるため、一時的なデータ保存先として、データのキャッシング、セッション管理、リアルタイム通知、ランキング、ジョブキューなどに活用できます。

インストール

まずはOSにRedisをインストールします。

brew install redis

OSによってインストール方法が変わってくるのでドキュメントにご参考ください。
https://redis.io/docs/getting-started/installation/

redisを立ち上げる

redis-serverでRedisをたちあげることができます。
Homebrewでインストールした場合、brew services start redisでも大丈夫です。

redis-server
36307:C 03 Sep 2023 00:13:08.506 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
36307:C 03 Sep 2023 00:13:08.506 * Redis version=7.2.0, bits=64, commit=00000000, modified=0, pid=36307, just started
36307:C 03 Sep 2023 00:13:08.506 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
36307:M 03 Sep 2023 00:13:08.507 * Increased maximum number of open files to 10032 (it was originally set to 256).
36307:M 03 Sep 2023 00:13:08.507 * monotonic clock: POSIX clock_gettime
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 7.2.0 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                  
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 36307
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           https://redis.io       
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

36307:M 03 Sep 2023 00:13:08.507 # WARNING: The TCP backlog setting of 511 cannot be enforced because kern.ipc.somaxconn is set to the lower value of 128.
36307:M 03 Sep 2023 00:13:08.508 * Server initialized
36307:M 03 Sep 2023 00:13:08.508 * Ready to accept connections tcp

デフォルトのポートは6379ですね。

redis-cliに入る

redis-cliを実行します。

➜ redis-cli
127.0.0.1:6379> 
➜ quit

redisの起動状況を確認する

ps aux | grep redis 
user               36307   0.0  0.0 34204452   2140   ??  S    12:13AM   1:17.56 redis-server *:6379

# redisをダウンする
kill 36307

基本のコマンド

コマンドを大文字にすると分かりやすいので大文字にしてます。小文字でも大丈夫です。
デフォルトのデータタイプはStringです。

# nameをtanakaに設定する
127.0.0.1:6379> SET name tanaka
OK
# nameをgetする
127.0.0.1:6379> GET name
"tanaka"
# ageを100に設定する
127.0.0.1:6379> SET age 100
OK
# ageをgetする
127.0.0.1:6379> GET age
"100"
# ageを削除する
127.0.0.1:6379> DEL age
(integer) 1
# ageをgetしようとnilが出る
127.0.0.1:6379> GET age
(nil)
# ageが存在しないため0(false)になる
127.0.0.1:6379> EXISTS age
(integer) 0
# nameが存在しているため1(True)になる
127.0.0.1:6379> EXISTS name
(integer) 1
# 全てのキーを取得する
127.0.0.1:6379> KEYS *
1) "name"
# 全てのデータを削除する
127.0.0.1:6379> flushall
OK
# キーがempty
127.0.0.1:6379> KEYS *
(empty array)

データの期限

127.0.0.1:6379> SET name tanaka
OK
# 有効期限をgetする
127.0.0.1:6379> ttl name
(integer) -1

TTL(Time To Live)は、データが有効である期間を表すための概念です。TTLが正の整数の場合、そのキー-値ペアは指定された秒数の間だけ有効です。一旦有効期限が切れると、データは自動的に削除されます。

TTL-1の場合、そのキー-値ペアには有効期限がありません。つまり、データは自動的に削除されることはありません。この設定は、Redis内のデータを永続的に保持するために使用できます。

データの期限を設定する

nameの期限を10秒に設定してみます。

# setex name 10 tanakaでもOK
127.0.0.1:6379> EXPIRE name 10
(integer) 1
# 秒数でカウントダウンされている
127.0.0.1:6379> ttl name
(integer) 5
127.0.0.1:6379> ttl name
(integer) 4
127.0.0.1:6379> ttl name
(integer) 3
127.0.0.1:6379> ttl name
(integer) 2
127.0.0.1:6379> ttl name
(integer) 1
# データが存在しない
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> GET name
(nil)

RedisのTTL(Time To Live)値において、-2はキーが存在しないことを示します。

  • 正の整数:キーが存在し、そのキー-値ペアの有効期限が秒単位で設定されています。
  • 0:キーが存在し、有効期限がすでに切れていることを示します。ただし、キー-値ペアは手動で削除されていない場合、まだ存在しています。
  • -1:キーが存在し、有効期限が設定されていないことを示します。つまり、キー-値ペアは永続的に存在します。
  • -2:キーが存在しないことを示します。この値は、指定したキーがRedisデータベース内に存在しない場合に返されます。

TTL値を-2で取得することは、指定したキーが存在しないか、EXPIREコマンドなどを使用して有効期限が設定されていない場合に有用です。データベース内の存在しないキーに対してTTLを確認すると、通常は-2が返されます。

配列/リストを扱う

127.0.0.1:6379> LPUSH friends tanaka
(integer) 1
127.0.0.1:6379> LRANGE friends 0 -1
1) "tanaka"

LPUSHのコマンドはfriendsという名前のリストに新しい要素tanakaをリストの先頭に追加します。LPUSHコマンドはリストの左側に要素を追加します(left push)。コマンドの実行後、1という整数が返されます。これはリスト内の要素の数を示します。

LRANGEコマンドは指定された範囲の要素をリストから取り出します。ここでは0から-1までの範囲を指定しているため、リスト内のすべての要素が返されます。

LRANGE friends 0 -1の実行結果で"tanaka"がリスト内に含まれていることが示されています。

# friendsリストにもう一人追加してみる
127.0.0.1:6379> LPUSH friends suzuki
(integer) 2
127.0.0.1:6379> LRANGE friends 0 -1
1) "suzuki"
2) "tanaka"

LPUSH以外、RPUSHもあります。
RPUSHは、新しい要素をリストの末尾に追加するコマンドです。具体的には、指定されたキーのリストに対して、要素を末尾に追加します。

配列/リストから削除する

LPOP(Left Pop)とRPOP(Right Pop)は、Redisのリスト(List)データ構造から要素を取り出すコマンドです。それぞれリストの左端と右端から要素を取り出します。

LPOP(左から取り出す):

  • LPOPコマンドは、リストの左端(先頭)から要素を取り出します。
  • リストから要素を取り出して、その要素を返します。
  • 取り出した要素はリストから削除されます。
127.0.0.1:6379> LPOP friends
"suzuki"

RPOP(右から取り出す):

  • RPOPコマンドは、リストの右端(末尾)から要素を取り出します。
  • リストから要素を取り出して、その要素を返します。
  • 取り出した要素はリストから削除されます。

setsを扱う

RedisのSets(集合)は、一意の要素の集まりを表すデータ構造です。
Setsは、重複を許さず、要素の順序を持たない特徴を持っています。

要素を追加する

Setsに要素を追加するには、SADDsets add)コマンドを使用します。このコマンドは、指定したキーのSetsに一意の要素を追加します。追加される要素が既に存在している場合、無視されます。

127.0.0.1:6379> SADD hobbies "watch movie"
(integer) 1
127.0.0.1:6379> SADD hobbies run
(integer) 1
# SMEMBER(sets member)でsetsのメンバーを確認する
127.0.0.1:6379> SMEMBERS hobbies
1) "watch movie"
2) "run"
# 重複した値を追加しようと0/flaseを返される
127.0.0.1:6379> SADD hobbies "watch movie"
(integer) 0

要素を削除する

SREMsets remove)コマンドを使用します。指定した要素をSetsから削除します。

127.0.0.1:6379> SREM hobbies "watch movie"
(integer) 1
127.0.0.1:6379> SREM hobbies run
(integer) 1
127.0.0.1:6379> SMEMBERS hobbies
(empty array)

要素の存在を確認する

Sets内に特定の要素が存在するかどうかを確認するには、SISMEMBERコマンドを使用します。

127.0.0.1:6379> SADD food banana
(integer) 1
127.0.0.1:6379> SADD food apple
(integer) 1
# orangeがfoodに存在しないのでfalseを返される
127.0.0.1:6379> SISMEMBER food orange
(integer) 0
127.0.0.1:6379> SISMEMBER food banana
(integer) 1

Setsの要素数を取得する

Sets内の要素数を取得するには、SCARDコマンドを使用します。

127.0.0.1:6379> SCARD food
(integer) 2

Setsの要素一覧を取得する

Sets内のすべての要素を一覧で取得するには、SMEMBERSコマンドを使用します。

127.0.0.1:6379> SMEMBERS food
1) "banana"
2) "apple"

ハッシュを扱う

ハッシュ(Hash)は、キー-値ペアのコレクションを格納するデータ構造です。
ハッシュは、1つのキーに関連付けられた複数のフィールドとその値を持ち、特に連想配列として使用されます。

ハッシュを作成する

ハッシュを作成するには、HSEThash set)コマンドを使用します。このコマンドは、指定されたキー内に新しいフィールドとその値を追加します。既存のキーにフィールドを追加するか、新しいキーを作成します。

127.0.0.1:6379> HSET person name tanaka
(integer) 1

personというキー内にnameというフィールドとその値"tanaka"を追加しました。

フィールドの値を取得:

ハッシュから特定のフィールドの値を取得するには、HGETコマンドを使用します。

127.0.0.1:6379> HGET person name
"tanaka"

personキー内のnameフィールドの値を返します。

ハッシュ内のすべてのフィールドと値を取得する

ハッシュ内のすべてのフィールドと値を取得するには、HGETALLコマンドを使用します。

127.0.0.1:6379> HGETALL person
1) "name"
2) "tanaka"

personキー内のすべてのフィールドと値を返します。

フィールドを削除する

ハッシュから特定のフィールドを削除するには、HDELhash delete)コマンドを使用します。

127.0.0.1:6379> HDEL person name
(integer) 1
# 削除されたことを確認する
127.0.0.1:6379> HGET person name
(nil)

personキー内のnameフィールドを削除します。

フィールドの存在を確認する

ハッシュ内に特定のフィールドが存在するかどうかを確認するには、HEXISTSコマンドを使用します。

# 存在しないのでfalseが返される
127.0.0.1:6379> HEXISTS person name
(integer) 0

personキー内にnameフィールドが存在するかどうかを確認します。

終わりに

Redisのインストール、CLI操作、とよく使うデータ型についてまとめてみました。

Discussion