Redis データ構造と主要コマンドの徹底解説

Redis 共通コマンドの基礎

Redis には数百ものコマンドが用意されていますが、すべてを暗記する必要はありません。Redis の内部機制を理解することで、コマンドの汎用性が見えてきます。ただし、データ構造やコマンドは特定のユースケースに適しており、誤った使用はパフォーマンス低下やアプリケーション障害を招く可能性があります。

キー管理に関するグローバルコマンド

特定のデータ型に依存せず、キー全体に対して操作を行うコマンドです。

KEYS

パターンに一致するすべてのキーを検索します。全キーを走査するため、本番環境での使用は慎重に行う必要があります。

KEYS pattern
# 戻り値:マッチしたキーのリスト
# 計算量:O(n)

EXISTS

指定したキーが存在するか確認します。

EXISTS key [key ...]
# 戻り値:存在するキーの数
# 計算量:O(1)

DEL

キーを削除します。

DEL key [key ...]
# 戻り値:削除されたキーの数
# 計算量:O(1)

EXPIRE と TTL

キーに有効期限を設定し、残存時間を取得します。

EXPIRE key seconds
# 戻り値:設定成功なら 1、失敗なら 0
# 計算量:O(1)

TTL key
# 戻り値:残存秒数。-1 は永続、-2 はキー不存在
# 計算量:O(1)

TYPE

キーに格納されている値のデータ型を返します。

TYPE key
# 戻り値:none, string, list, set, zset, hash, stream

String 型(文字列)

Redis のデータ型は、主に値(value)の構造を指します。String 型は最も基本的な型です。

内部エンコーディング

Redis は値のタイプとサイズに応じて内部表現を動的に変更します。

  • int: 8 バイトの符号付き長整数。
  • embstr: 39 バイト以下の文字列。
  • raw: 39 バイトを超える文字列。

主要コマンド

SET / GET

キーに文字列値を設定・取得します。キーが存在する場合は上書きされ、既存の TTL は無効になります。

SET key value [EX seconds|PX milliseconds] [NX|XX]
# 計算量:O(1)
# 选项:EX/PX で有効期限設定。NX は不存在時のみ設定、XX は存在時のみ設定

GET key
# 計算量:O(1)
# 戻り値:値、またはキー不存在なら nil

使用例:

redis> SET session_token "usr_9988" EX 300
OK
redis> GET session_token
"usr_9988"
redis> SET session_token "usr_7766" NX
(nil)
# キーが存在するため NX は失敗

MSET / MGET

複数のキーに対して同時に設定・取得を行います。ネットワークラウンドトリップを減らす効果があります。

MSET key value [key value ...]
MGET key [key ...]
# 計算量:O(N)

数値操作(INCR / DECR)

文字列を整数として解釈し、増減算を行います。キーが存在しない場合は 0 として扱われます。

INCR key
INCRBY key increment
DECR key
DECRBY key decrement
# 計算量:O(1)
# 非整数または範囲外の場合はエラー

使用例:

redis> INCR counter:page_view
(integer) 1
redis> INCR counter:page_view
(integer) 2
redis> SET counter:page_view "invalid"
OK
redis> INCR counter:page_view
(error) value is not an integer or out of range

INCRBYFLOAT

浮動小数点数の加算を行います。科学記数法もサポートされています。

redis> SET metric:load 10.5
OK
redis> INCRBYFLOAT metric:load 0.5
"11"

文字列操作(APPEND / GETRANGE / SETRANGE)

文字列の追加、部分取得、部分上書きを行います。

APPEND key value
# 戻り値:追加後の長さ

GETRANGE key start end
# 部分文字列を取得(インデックスは 0 開始、負数可)

SETRANGE key offset value
# 指定オフセットから値を上書き

使用事例

キャッシュ、カウンタ(アクセス数など)、セッション管理、ワンタイムパスワードなど。

Hash 型(ハッシュ)

フィールドと値のマップを保持します。オブジェクトの保存に適しています。

主要コマンド

HSET key field value [field value ...]
# 計算量:O(1)〜O(N)
# 戻り値:新規追加されたフィールド数

HGET key field
# 計算量:O(1)

HEXISTS key field
# 計算量:O(1)
# 戻り値:存在すれば 1、否则 0

HDEL key field [field ...]
# 計算量:O(1)〜O(N)

HKEYS / HVALS / HGETALL
# キー、値、または全てのフィールドと値を取得

HMGET key field [field ...]
# 複数のフィールドを一度に取得

HLEN key
# フィールド数を取得

HSETNX key field value
# フィールド不存在時のみ設定

HINCRBY / HINCRBYFLOAT
# フィールド値の数値増減

HSTRLEN key field
# フィールド値の文字列長

使用例:

redis> HSET user:1001 name "Suzuki" age 30
(integer) 2
redis> HGET user:1001 name
"Suzuki"
redis> HINCRBY user:1001 login_count 1
(integer) 1

内部エンコーディング

  • ziplist: エントリ数と値のサイズが閾値(默认 512 エントリ、64 バイト)以下の場合。メモリ効率が良い。
  • hashtable: 閾値を超えた場合。读写性能は O(1)。

使用事例

ユーザー情報、商品詳細など、構造化されたデータの保存。JSON よりも細粒度な更新が可能。

List 型(リスト)

文字列のリストを保持します。要素は順序付けられており、重複を許可します。両端からの挿入・削除が可能です。

主要コマンド

LPUSH / RPUSH
# 左端(頭)または右端(尾)に要素を挿入

LPUSHX / RPUSHX
# キーが存在する場合のみ挿入

LRANGE key start stop
# 指定範囲の要素を取得(閉区間)

LPOP / RPOP
# 左端または右端の要素を取得し削除

LINDEX key index
# 指定インデックスの要素取得

LINSERT key BEFORE|AFTER pivot element
# 指定要素の前後に挿入

LLEN key
# リストの長さを取得

使用例:

redis> LPUSH queue:jobs "task_A"
(integer) 1
redis> LPUSH queue:jobs "task_B"
(integer) 2
redis> LRANGE queue:jobs 0 -1
1) "task_B"
2) "task_A"
redis> RPOP queue:jobs
"task_A"

ブロッキングコマンド(BLPOP / BRPOP)

リストが空の場合、指定タイムアウトまでブロックして要素を待機します。メッセージキューの実装に有用です。

BLPOP key [key ...] timeout
# 戻り値:[キー,要素] または nil

内部エンコーディング

  • ziplist: 要素数とサイズが小さい場合。
  • linkedlist: 条件を満たさない場合。双方向リンクリスト。

使用事例

メッセージキュー、タイムライン、最新順のリストなど。

Set 型(集合)

重複のない文字列の集合です。順序は保証されません。

主要コマンド

SADD key member [member ...]
# 要素を追加(重複は無視)
# 戻り値:新規追加数

SMEMBERS key
# 全要素を取得

SISMEMBER key member
# 要素の存在確認

SCARD key
# 要素数を取得

SPOP key [count]
# 要素をランダムに削除して返回

SMOVE source dest member
# 要素を別のセットへ移動

SREM key member [member ...]
# 要素を削除

集合演算

SINTER key [key ...]
# 共通部分(積集合)

SUNION key [key ...]
# 全体集合(和集合)

SDIFF key [key ...]
# 差集合

# 結果を保存する STORE コマンドも用意されています(SINTERSTORE など)

使用例:

redis> SADD tags:post1 "redis" "db"
(integer) 2
redis> SADD tags:post2 "redis" "cache"
(integer) 2
redis> SINTER tags:post1 tags:post2
1) "redis"

内部エンコーディング

  • intset: 要素がすべて整数で、数が閾値(默认 512)以下の場合。
  • hashtable: それ以外の場合。

使用事例

タグ管理、共通の趣味を持つユーザーの発見、ブラックリスト/ホワイトリストなど。

Zset 型(ソート済み集合)

各要素にスコア(浮動小数点数)を紐付け、スコア順にソートされた集合です。重複メンバーは許可されませんが、スコアは重複可能です。

主要コマンド

ZADD key [NX|XX] [CH] [INCR] score member [score member ...]
# 要素とスコアを追加・更新
# 計算量:O(log(N))

ZCARD key
# 要素数を取得

ZCOUNT key min max
# 指定スコア範囲の要素数をカウント

ZRANGE key start stop [WITHSCORES]
# スコア昇順で範囲取得

ZREVRANGE key start stop [WITHSCORES]
# スコア降順で範囲取得

ZRANGEBYSCORE key min max [WITHSCORES]
# スコア範囲で要素取得

ZPOPMAX / ZPOPMIN
# スコア最大/最小の要素を削除して返回

ZRANK / ZREVRANK
# 要素のランク(順位)を取得

ZSCORE key member
# 要素のスコアを取得

ZREM key member [member ...]
# 要素を削除

ZREMRANGEBYRANK / ZREMRANGEBYSCORE
# ランクまたはスコア範囲で要素を削除

ZINCRBY key increment member
# スコアを増減

ZINTERSTORE / ZUNIONSTORE
# 複数 Zset の積集合・和集合を計算し保存

使用例:

redis> ZADD ranking:daily 100 "player_A"
(integer) 1
redis> ZADD ranking:daily 250 "player_B"
(integer) 1
redis> ZREVRANGE ranking:daily 0 -1 WITHSCORES
1) "player_B"
2) "250"
3) "player_A"
4) "100"
redis> ZINCRBY ranking:daily 50 "player_A"
"150"

内部エンコーディング

  • ziplist: 要素数と値のサイズが閾値(默认 128 エントリ、64 バイト)以下の場合。
  • skiplist: 条件を満たさない場合。跳び表構造により効率的な範囲検索を実現。

使用事例

ランキングシステム、優先度キュー、時間順のイベントログなど。

SCAN コマンドによる漸進的走査

KEYS コマンドは全キーを走査するため、キー数が多い場合に Redis をブロックするリスクがあります。SCAN コマンドはカーソルを使用して漸進的にキーを走査し、サーバーへの負荷を分散します。

SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]
# 計算量:1 回の呼び出しで O(1)
# 戻り値:[次のカーソル,キーのリスト]

走査は cursor 0 から開始し、返回されるカーソルが 0 になった時点で完了です。

使用例:

redis> SCAN 0 MATCH user:* COUNT 10
1) "15"
2) 1) "user:101"
   2) "user:102"
   ...
redis> SCAN 15 MATCH user:* COUNT 10
1) "0"
2) 1) "user:103"
   ...
# カーソルが 0 に戻れば終了

タグ: redis data-structures NoSQL Caching Backend-Engineering

7月13日 22:54 投稿