Redisのキー管理

キーはRedisにおけるデータの基本単位です。このレッスンでは、キー管理の操作について解説します。

基本的なキー操作

キーの設定

REDIS
# 文字列を設定
SET user:1 "Alice"

# ハッシュを設定
HSET user:2 name "Bob" age 30

# リストを設定
LPUSH articles "article1" "article2"

# セットを設定
SADD tags:article1 "redis" "database"

# ソート済みセットを設定
ZADD leaderboard 100 "player1"

キーの取得

REDIS
# 文字列を取得
GET user:1

# ハッシュを取得
HGETALL user:2

# リストを取得
LRANGE articles 0 -1

# セットを取得
SMEMBERS tags:article1

# ソート済みセットを取得
ZRANGE leaderboard 0 -1 WITHSCORES

キーの削除

REDIS
# 単一のキーを削除
DEL user:1
(integer) 1  # 削除されたキーの数を返す

# 複数のキーを削除
DEL user:2 user:3
(integer) 2

# 存在しないキーを削除
DEL notexist
(integer) 0

キーの存在確認

REDIS
SET mykey "hello"

EXISTS mykey
(integer) 1  # 存在する

EXISTS notexist
(integer) 0  # 存在しない

# 複数のキーを確認(存在するキーの数を返す)
EXISTS mykey mykey2 mykey3
(integer) 1  # mykeyのみ存在する

キーの型を確認

REDIS
SET mystring "hello"
TYPE mystring          # string

HSET myhash field "value"
TYPE myhash            # hash

LPUSH mylist "a"
TYPE mylist            # list

SADD myset "a"
TYPE myset             # set

ZADD myzset 1 "a"
TYPE myzset            # zset

TYPE notexist          # none

キーの命名規則

適切なキー命名により、データ管理が明確になります。

推奨形式

business:object:ID[:property]

REDIS
# ユーザー情報
user:1                  # ユーザー1の基本情報
user:1:profile          # ユーザー1の詳細プロフィール
user:1:settings         # ユーザー1の設定

# 記事
article:123             # 記事123の内容
article:123:comments    # 記事123のコメントリスト
article:123:views       # 記事123の閲覧数

# ショッピングカート
cart:user:1             # ユーザー1のショッピングカート

# セッション
session:token:abc123    # セッショントークン

# キャッシュ
cache:api:user:1        # ユーザー1情報のAPIキャッシュ
cache:page:home         # ホームページのページキャッシュ

# ロック
lock:order:123          # 注文123のロック
▶ 試してみよう

命名の提案

提案 説明
コロンを区切り文字に user:1:profile 明確な階層
意味のあるプレフィックスを使用 cache:session:lock: 異なる目的を区別
一貫性を保つ user:1user:2 統一された形式
長くなりすぎないように u:1:p 短すぎると不明瞭、長すぎるとメモリ使用
特殊文字を避ける user-1 ハイフンやコロンを使用し、スペースは避ける
💡 キーの長さ: キー名はメモリを消費します。明確さと簡潔さのバランスを取りましょう。頻繁に使用するキーは短くできます。

有効期限

RedisはキーにTTL(生存時間)を設定でき、期限が切れると自動的に削除されます。

有効期限の設定

REDIS
SET session:token123 "user_data"

# 方法1:EXPIRE(秒)
EXPIRE session:token123 3600    # 1時間後に期限切れ

# 方法2:EXPIREAT(タイムスタンプ、秒)
EXPIREAT session:token123 1700000000

# 方法3:PEXPIRE(ミリ秒)
PEXPIRE session:token123 3600000

# 方法4:PEXPIREAT(タイムスタンプ、ミリ秒)
PEXPIREAT session:token123 1700000000000

# 方法5:SETで有効期限を設定
SET cache:key "value" EX 60     # 60秒後に期限切れ
SET cache:key "value" PX 60000  # 60000ミリ秒後に期限切れ

有効期限の確認

REDIS
# TTL:残り時間を返す(秒)
TTL session:token123
(integer) 3500  # 残り3500秒

# PTTL:残り時間を返す(ミリ秒)
PTTL session:token123
(integer) 3500000

# 特別な戻り値
TTL noexpire
(integer) -1    # キーは存在するが有効期限がない

TTL notexist
(integer) -2    # キーが存在しない

有効期限の削除

REDIS
# PERSIST:有効期限を削除して、キーを永続化
PERSIST session:token123
(integer) 1  # 正常に削除

PERSIST notexist
(integer) 0  # キーが存在しない

有効期限のユースケース

シナリオ TTL
セッション 30分 SET session:token "data" EX 1800
確認コード 5分 SET code:phone:138xxxx "123456" EX 300
キャッシュ 1時間 SET cache:api:user:1 "data" EX 3600
レート制限 1分 SET limit:user:1 "10" EX 60
分散ロック 10秒 SET lock:resource "locked" NX EX 10
⚠️ 補足: 有効期限の精度はミリ秒ですが、実際の削除は遅延する可能性があります(遅延削除 + 定期的な削除)。

キーの名前変更

RENAME:キーの名前変更

REDIS
SET oldkey "value"

RENAME oldkey newkey
OK

GET newkey
"value"

GET oldkey
(nil)  # oldkeyはもう存在しない
⚠️ 補足: newkeyがすでに存在する場合、RENAMEはそれを上書きします!

RENAMENX:新しいキーが存在しない場合のみ名前変更

REDIS
SET key1 "value1"
SET key2 "value2"

RENAMENX key1 key2
(integer) 0  # key2はすでに存在するため、名前変更に失敗

GET key1
"value1"  # key1はまだ存在する

GET key2
"value2"  # key2は上書きされなかった

キーの移行

MOVE:キーを別のデータベースに移動

REDIS
# DB 0で
SET mykey "value"

# DB 1に移動
MOVE mykey 1
(integer) 1  # 成功

# DB 1に切り替え
SELECT 1
OK

GET mykey
"value"
⚠️ 補足: MOVEはクラスターモードでは使用できません。

DUMP + RESTORE:シリアル化とデシリアル化

REDIS
# キーをシリアル化
SET mykey "hello"
DUMP mykey
# シリアル化されたバイナリデータを返す

# 新しいキーに復元
RESTORE newkey 0 "\x00\x05hello\t\x00\xf5\xbd\xba\xab\xdc\xa6\xdec"
OK

MIGRATE:キーを別のRedisインスタンスに移行

REDIS
# mykeyを192.168.1.100:6379に移行
MIGRATE 192.168.1.100 6379 mykey 0 5000
OK

# パラメータの説明
# MIGRATE host port key destination-db timeout

キーのソート

SORTコマンドはリスト、セット、ソート済みセットをソートできます。

基本ソート

REDIS
# リストをソート
LPUSH mylist 3 1 4 1 5 9 2 6
SORT mylist
# 1) "1"
# 2) "1"
# 3) "2"
# 4) "3"
# 5) "4"
# 6) "5"
# 7) "6"
# 8) "9"

# 降順ソート
SORT mylist DESC
# 1) "9"
# 2) "6"
# 3) "5"
# ...

# セットをソート
SADD myset 5 2 8 1 9
SORT myset
# 1) "1"
# 2) "2"
# 3) "5"
# 4) "8"
# 5) "9"

外部値によるソート

REDIS
# 学生IDリスト
LPUSH students "student1" "student2" "student3"

# 学生のスコア
SET student1:score 85
SET student2:score 92
SET student3:score 78

# スコアでソート
SORT students BY *:score
# 1) "student3"  # 78点
# 2) "student1"  # 85点
# 3) "student2"  # 92点

# 外部値を取得
SORT students BY *:score GET *:score
# 1) "78"
# 2) "85"
# 3) "92"

ソート結果の保存

REDIS
# ソートして新しいキーに保存
SORT mylist DESC STORE sorted_list
(integer) 8

LRANGE sorted_list 0 -1
# 1) "9"
# 2) "6"
# ...

キーの検索

KEYS:一致するキーを検索

REDIS
# テストデータを設定
SET user:1 "Alice"
SET user:2 "Bob"
SET user:3 "Charlie"
SET product:1 "iPhone"
SET product:2 "iPad"

# すべてのキーを検索
KEYS *
# 1) "user:1"
# 2) "user:2"
# 3) "user:3"
# 4) "product:1"
# 5) "product:2"

# パターンに一致するキーを検索
KEYS user:*
# 1) "user:1"
# 2) "user:2"
# 3) "user:3"

KEYS *:1
# 1) "user:1"
# 2) "product:1"

KEYS user:[1-2]
# 1) "user:1"
# 2) "user:2"
⚠️ 注意: KEYSはデータベース全体をスキャンします。大規模なデータセットでは非常に遅いため、本番環境では使用しないでください

SCAN:キーを反復処理(推奨)

SCANはKEYSの安全な代替手段で、カーソルベースの反復処理を使用します。

REDIS
# 反復処理を開始、カーソルとキーリストを返す
SCAN 0
1) "5"          # 次の反復処理のカーソル
2) 1) "user:1"
   2) "user:2"

# 反復処理を続行
SCAN 5
1) "0"          # カーソルが0の場合は反復処理完了
2) 1) "user:3"
   2) "product:1"

# パターンマッチ
SCAN 0 MATCH user:*
1) "3"
2) 1) "user:1"
   2) "user:2"

# 反復処理ごとの件数を指定
SCAN 0 COUNT 100

SCANファミリーコマンド

REDIS
# セット要素を反復処理
SSCAN myset 0

# ハッシュフィールドを反復処理
HSCAN myhash 0

# ソート済みセット要素を反復処理
ZSCAN myzset 0
💡 SCANの利点: サーバーをブロックせず、大量のキーをバッチで処理できます。

キースペース通知

Redisはキーの変更イベントについてクライアントに通知できます。

キースペース通知の設定

REDIS
# 設定を表示
CONFIG GET notify-keyspace-events
1) "notify-keyspace-events"
2) ""  # デフォルトでは無効

# すべての通知を有効化
CONFIG SET notify-keyspace-events AKE
OK

通知の種類

文字 通知タイプ 説明
K Keyspace キースペース通知(keyspace@
E Keyevent キーイベント通知(keyevent@
A All すべての通知(KE$glshと同等)
$ String 文字列コマンド
l List リストコマンド
s Set セットコマンド
h Hash ハッシュコマンド
z Sorted Set ソート済みセットコマンド
x Expired 有効期限イベント
e Evicted 削除イベント(メモリ削除)

通知のサブスクライブ

REDIS
# キースペース通知をサブスクライブ(キーのすべてのイベント)
SUBSCRIBE __keyspace@0__:mykey

# キーイベント通知をサブスクライブ(すべてのキーの特定のイベント)
SUBSCRIBE __keyevent@0__:set

例:期限切れキーの監視

REDIS
# 設定:期限切れ通知を有効化
CONFIG SET notify-keyspace-events Ex
OK

# クライアント1:期限切れイベントをサブスクライブ
SUBSCRIBE __keyevent@0__:expired

# クライアント2:有効期限付きのキーを設定
SET temp "value" EX 5

# クライアント1が受信:
# 1) "message"
# 2) "__keyevent@0__:expired"
# 3) "temp"  # 期限切れのキー名
▶ 試してみよう

キー情報

OBJECTコマンド

REDIS
SET mykey "hello"

# キーの内部エンコーディングを表示
OBJECT ENCODING mykey
"embstr"

# 参照カウントを表示
OBJECT REFCOUNT mykey
(integer) 1

# アイドル時間を表示(秒)
OBJECT IDLETIME mykey
(integer) 10

MEMORYコマンド(Redis 4.0+)

REDIS
SET mykey "hello world hello world hello world"

# キーのメモリ使用量を表示
MEMORY USAGE mykey
(integer) 56  # バイト

# メモリ割り当ての詳細を表示
MEMORY STATS

STRLEN:文字列の長さを取得

REDIS
SET mykey "Hello Redis"
STRLEN mykey
(integer) 11

バッチ操作

バッチ設定

REDIS
MSET key1 "value1" key2 "value2" key3 "value3"
OK

バッチ取得

REDIS
MGET key1 key2 key3
1) "value1"
2) "value2"
3) "value3"

# 存在しないキーを含む場合
MGET key1 key2 notexist key3
1) "value1"
2) "value2"
3) (nil)
4) "value3"

バッチ削除

REDIS
# 複数のキーを削除
DEL key1 key2 key3
(integer) 3

❓ よくある質問

Q KEYSコマンドが遅いのはなぜですか?
A KEYSはO(N)の時間複雑度でデータベース全体をスキャンします。データセットが大きいとRedisをブロックします。代わりにSCANを使用してください。
Q 期限切れのキーはいつ削除されますか?
A Redisは遅延削除+定期的な削除を使用します。キーにアクセスしたときに有効期限をチェックし、バックグラウンドでランダムなキーのサンプルを定期的にチェックします。
Q パターンに一致するキーをバッチ削除するにはどうすればよいですか?
A

BASH
redis-cli --scan --pattern "prefix:*" | xargs redis-cli DEL

Q:キー名の最大長は? A:理論上は無制限ですが、短くすることを推奨します(メモリを消費します)。

Q 特定の型のキーをカウントするにはどうすればよいですか?
A 直接のコマンドはありません。SCANで反復処理し、TYPEで確認する必要があります。

📖 まとめ

  • 基本的なキー操作:SET、GET、DEL、EXISTS、TYPE
  • キーの命名:コロンを区切り文字とし、意味のあるプレフィックスを使用
  • 有効期限:EXPIRE、TTL、PERSIST
  • キーの検索:KEYS(注意して使用)、SCAN(推奨)
  • キーの移行:MOVE、MIGRATE、DUMP/RESTORE
  • キーのソート:SORTコマンド
  • キースペース通知:キーの変更イベントをリスン

📝 練習問題

  1. 命名の練習: eコマースサイト(ユーザー、商品、注文、ショッピングカート)のキー命名規則を設計しましょう
  2. 有効期限の練習: TTL付きのキーを設定し、TTLで残り時間を確認し、期限切れ後に確認しましょう
  3. SCANの練習: 100個のキーを作成し、SCANを使用してすべてを反復処理しましょう
  4. バッチ操作: MSETで10個のキーを設定し、MGETで取得しましょう

次のレッスン

次のレッスンでは、Redis Strings(パート1)について学びます。基本的な文字列操作を詳しく解説します。

100%