はい、承知いたしました。「Redisコマンド入門:これだけは押さえたい基本操作」と題し、約5000語の詳細な解説記事を作成します。内容はMarkdown形式で直接出力します。
Redisコマンド入門:これだけは押さえておきたい基本操作
データ構造ストアとして人気を博しているRedisは、その高速なデータアクセスと多様なデータ構造により、キャッシュ、メッセージキュー、セッションストア、リアルタイム分析など、幅広いユースケースで活用されています。Redisを効果的に利用するためには、その核となるコマンドを理解することが不可欠です。
この記事では、Redisを使い始めるにあたって「これだけは押さえておきたい」基本的なコマンドに焦点を当て、それぞれのコマンドについて構文、機能、使用例、注意点を詳細に解説します。この記事を通じて、Redisコマンドの基本をマスターし、Redis活用の第一歩を踏み出しましょう。
1. Redisとは?なぜRedisコマンドを学ぶのか?
Redisとは
Redis(Remote Dictionary Server)は、オープンソースのインメモリデータ構造ストアです。データをRAM上に保持するため、非常に高速な読み書きが可能です。永続化の仕組みも備えているため、データの消失リスクを低減できます。単なるキー・バリュー型ストアにとどまらず、文字列(String)、リスト(List)、セット(Set)、ソート済みセット(Sorted Set)、ハッシュ(Hash)といった様々なデータ構造をネイティブにサポートしており、これらのデータ構造に対する豊富な専用コマンドを提供しています。
なぜRedisコマンドを学ぶのか
- Redisの理解: Redisの真価は、その多様なデータ構造と、それらを操作するための効率的なコマンド群にあります。コマンドを学ぶことで、Redisがどのようなデータをどのように扱えるのかを深く理解できます。
- 効率的な開発: 各データ構造とコマンドの特性を把握することで、アプリケーションの要件に最適なデータ構造を選択し、効率的なデータ操作を実装できます。例えば、ランキング機能にはSorted Set、ユニークな要素のコレクションにはSet、キューにはListが適しています。
- デバッグと運用: Redisのクライアント(
redis-cliなど)から直接コマンドを実行できるようになることは、開発中のデバッグや、本番環境でのデータ確認、簡単な操作、問題発生時の診断において非常に役立ちます。 - 基盤知識: クライアントライブラリを通じてアプリケーションからRedisを利用する場合も、結局はその内部でこれらの基本コマンドが発行されています。基盤となるコマンドを知っていることで、ライブラリの動作や発生する可能性のある問題をよりよく理解できます。
この記事では、特に利用頻度の高い基本的なコマンドを中心に解説します。
2. Redisの主要なデータ構造
Redisがサポートするデータ構造は、単なるバイナリセーフなStringだけでなく、プログラムでよく使われる多様な構造を含んでいます。コマンドを学ぶ前に、これらのデータ構造がそれぞれどのような特徴を持っているのかを理解しておきましょう。
2.1 String (文字列)
- 特徴: 最も基本的なデータ型です。キーと値のペアで、値はバイナリセーフな文字列です。テキストはもちろん、画像データやシリアライズされたオブジェクトなど、様々な形式のデータを格納できます。最大サイズは512MBです。
- 用途: キャッシュ(WebページのHTML、APIレスポンス)、セッション情報、カウンター、単一の値の設定情報など。
2.2 List (リスト)
- 特徴: 挿入された順序を保持する文字列のリストです。双方向リストとして実装されており、リストの先頭または末尾からの要素の追加(Push)や削除(Pop)が高速(O(1))に行えます。リスト内の指定したインデックスの要素にアクセスしたり、指定した範囲の要素を取得したりもできますが、インデックスアクセスはリストの長さに応じて遅くなる場合があります(O(N))。
- 用途: キュー(タスクキュー)、スタック、最新データのリスト、タイムライン、Publish/Subscribeパターンの実装の一部など。
2.3 Set (セット)
- 特徴: 順序を持たない文字列の集合です。同じ要素を複数追加しても、セット内にはユニークな要素が1つだけ保持されます。要素の追加、削除、存在チェックは非常に高速(平均O(1))です。複数のセット間の和集合、積集合、差集合といった集合演算もサポートしています。
- 用途: ユニークな訪問者数のカウント、タグ付けシステム、アクセス権限管理、友達リスト(共通の友達を探すなど)。
2.4 Sorted Set (ソート済みセット / Zset)
- 特徴: セットと同様にユニークな文字列の集合ですが、各要素に「スコア」と呼ばれる浮動小数点数の値が関連付けられています。このスコアに基づいて、要素が常にソートされた状態で保持されます。要素の追加、削除、スコアの更新、スコアや順位による範囲検索(要素の取得)などが可能です。
- 用途: ランキングシステム(ゲームのスコアランキング、商品の売上ランキング)、レート制限(レートごとにユーザーを管理)、タイムスタンプによるソートが必要なデータ(イベントの発生順)。
2.5 Hash (ハッシュ)
- 特徴: フィールド(Field)と値(Value)のペアの集合を値として持つデータ構造です。一つのキーに対して複数のフィールドを持つことができます。フィールドと値はどちらも文字列です。個々のフィールドに対する追加、取得、削除が高速(平均O(1))です。
- 用途: オブジェクトの表現(ユーザーオブジェクト、商品情報など)、複数の関連するデータをまとめて管理する場合。例えば、キーをユーザーIDとし、フィールドを
name、age、emailなどとしてユーザー情報を格納する。
これらのデータ構造は、それぞれ得意なこと・不得意なことがあります。アプリケーションの要件に合わせて適切なデータ構造を選択することが、Redisを効果的に活用する鍵となります。
3. 基本的な共通コマンド
ここでは、特定のデータ構造に依存せず、全てのキーに対して利用できる基本的なコマンドを解説します。
3.1 KEYS
指定したパターンにマッチする全てのキー名を検索します。
- 構文:
KEYS pattern - 説明:
patternには glob スタイルのパターン(例:*,?,[])を指定します。*: 任意の文字列にマッチ?: 任意の一文字にマッチ[]: ブラケット内の任意の一文字にマッチ (例:[abc]は ‘a’, ‘b’, ‘c’ のいずれかにマッチ)
- 使用例:
- 全てのキーを取得:
KEYS * user:で始まるキーを取得:KEYS user:*dataまたはinfoで終わるキーを取得:KEYS *data *info(スペース区切りで複数指定はできません。パターンは一つだけです。)KEYS *dataとKEYS *infoを別々に実行するか、より複雑なパターンを使います。
- 全てのキーを取得:
- 戻り値: マッチしたキー名のリスト。マッチするキーがない場合は空のリスト。
- 注意点:
KEYSコマンドは、キーの数が多いデータベースに対して実行すると、Redisサーバーをブロックし、他のコマンドの処理を遅延させる可能性があります。 特に本番環境での使用は推奨されません。大量のキーを安全に取得・走査したい場合は、代わりにSCANコマンドを使用することを強く推奨します(SCANは本記事では深く扱いませんが、キーの走査において非常に重要なコマンドです)。KEYSは主に開発やデバッグ目的で使用します。
3.2 EXISTS
指定したキーが存在するかどうかを確認します。
- 構文:
EXISTS key [key ...] - 説明: 1つ以上のキー名を指定できます。
- 使用例:
- 単一のキーが存在するか確認:
EXISTS mykey - 複数のキーが存在するか確認:
EXISTS key1 key2 key3
- 単一のキーが存在するか確認:
- 戻り値: 指定したキーのうち、存在したキーの数。
- 時間計算量: O(N) ただし N は指定したキーの数。特定のキーの存在チェックは O(1) です。
3.3 DEL
指定したキーとそれに関連付けられた値を削除します。
- 構文:
DEL key [key ...] - 説明: 1つ以上のキー名を指定できます。
- 使用例:
- 単一のキーを削除:
DEL mykey - 複数のキーを削除:
DEL key1 key2 key3
- 単一のキーを削除:
- 戻り値: 削除されたキーの数。
- 時間計算量: O(N) ただし N は削除するキーの数。特定のキーの削除は平均 O(1) ですが、リストやセット、ハッシュなど内部構造が複雑なキーの削除は、要素数に比例して遅くなる場合があります(O(M)、Mは要素数)。
3.4 TYPE
指定したキーに格納されている値のデータ構造のタイプを確認します。
- 構文:
TYPE key - 説明: 指定したキーが存在しない場合は
noneを返します。 - 使用例:
TYPE mylist - 戻り値:
string,list,set,zset,hash, またはnone。 - 時間計算量: O(1)
3.5 RENAME
キーの名前を変更します。
- 構文:
RENAME oldkey newkey - 説明:
oldkeyが存在しない場合はエラーになります。もしnewkeyが既に存在する場合、そのキーは上書き(削除)されます。 - 使用例:
RENAME users:1 users:001 - 戻り値: OK (成功時)。エラー発生時はエラー応答。
- 時間計算量: O(1)
3.6 TTL / EXPIRE / PERSIST
キーに有効期限を設定したり、削除したり、有効期限を解除したりするコマンドです。
- EXPIRE: キーに秒単位の有効期限を設定します。
- 構文:
EXPIRE key seconds - 説明:
seconds後にキーが自動的に削除されるように設定します。既に有効期限が設定されている場合、新しい有効期限で上書きされます。有効期限が無限の場合も上書きされます。secondsを0以下にすると、キーは即座に削除されます(ただし通常は正の値を指定します)。 - 使用例:
EXPIRE mykey 60(mykey を60秒後に削除) - 戻り値: 1 (成功), 0 (キーが存在しない、または有効期限設定に失敗)
- 時間計算量: O(1)
- 構文:
- TTL: キーの残り有効期限(秒単位)を取得します。
- 構文:
TTL key - 説明: 有効期限までの残り秒数を返します。
- 戻り値: 残り秒数。-1 はキーが存在するが有効期限が設定されていない場合。-2 はキーが存在しない場合。
- 時間計算量: O(1)
- 構文:
- PERSIST: キーに設定されている有効期限を解除し、永続化(削除されない状態)に戻します。
- 構文:
PERSIST key - 説明: 有効期限を持つキーにのみ有効です。
- 使用例:
PERSIST mykey(mykey の有効期限設定を解除) - 戻り値: 1 (有効期限が解除された), 0 (キーが存在しない、または有効期限が設定されていなかった)
- 時間計算量: O(1)
- 構文:
- その他関連コマンド:
PEXPIRE key milliseconds: ミリ秒単位で有効期限を設定。PTTL key: ミリ秒単位で残り有効期限を取得。EXPIREAT key timestamp: 指定したUnixタイムスタンプ(秒)で有効期限を設定。PEXPIREAT key milliseconds-timestamp: 指定したUnixタイムスタンプ(ミリ秒)で有効期限を設定。
有効期限は、キャッシュの管理など、一定時間後に不要になるデータを自動的にクリーンアップする際に非常に便利です。
3.7 MOVE
指定したキーを現在のデータベースから別のデータベースに移動します。
- 構文:
MOVE key db - 説明:
dbは移動先のデータベースのインデックス番号(0から始まります)。移動先のデータベースに同じキーが存在する場合、MOVEコマンドは失敗します。 - 使用例:
MOVE mykey 1(現在のデータベースからデータベース1へ mykey を移動) - 戻り値: 1 (成功), 0 (キーが存在しない、または移動先のデータベースに同じキーが既に存在)
- 時間計算量: O(1)
4. String (文字列) コマンド
String は最も単純で汎用的なデータ型です。ここではString値を操作する基本的なコマンドを解説します。
4.1 SET
キーに文字列値を設定します。既にキーが存在する場合、古い値は上書きされます。
- 構文:
SET key value [EX seconds] [PX milliseconds] [NX|XX] - 説明:
key: 設定するキーの名前。value: 設定する値。バイナリセーフな文字列です。- オプション:
EX seconds: 指定した秒数後にキーがexpire(削除)されるように設定します。PX milliseconds: 指定したミリ秒数後にキーがexpireされるように設定します。NX: キーが存在しない場合にのみ設定を行います(”Not eXists”)。新しいキーの作成にのみ成功します。XX: キーが存在する場合にのみ設定を行います(”eXists”)。既存のキーの更新にのみ成功します。
- 使用例:
- 単純な設定:
SET mykey "hello" - 有効期限付き設定:
SET cache:page:1 <html> ... </html> EX 3600(3600秒 = 1時間後に削除) - キーが存在しない場合のみ設定:
SET user:1:lock true NX(ロック取得によく使われます) - キーが存在する場合のみ更新:
SET user:1:status online XX
- 単純な設定:
- 戻り値: OK (成功時)。
NXまたはXXオプションを使用し、条件に合わなかった場合は Nil応答。エラー発生時はエラー応答。 - 時間計算量: O(1)
4.2 GET
指定したキーの文字列値を取得します。
- 構文:
GET key - 説明: 指定したキーが存在しない場合、またはキーに関連付けられた値がString型でない場合はNil応答を返します。
- 使用例:
GET mykey - 戻り値: キーの値の文字列、またはNil応答。
- 時間計算量: O(1)
4.3 MSET / MGET
複数のキーと値を一度に設定(MSET)したり、複数のキーの値を一度に取得(MGET)したりするコマンドです。ネットワークのラウンドトリップ回数を減らし、効率を向上させます。
- MSET:
- 構文:
MSET key1 value1 key2 value2 ... - 説明: 複数のキーと値のペアを引数に取ります。全ての設定操作はアトミックに行われます。
- 使用例:
MSET user:1:name Alice user:1:age 30 user:2:name Bob - 戻り値: OK (常に成功時)。
- 時間計算量: O(N) ただし N は設定するキーの数。
- 構文:
- MGET:
- 構文:
MGET key1 key2 ... - 説明: 複数のキー名を引数に取ります。
- 使用例:
MGET user:1:name user:2:name user:3:name - 戻り値: 指定したキーに対応する値のリスト。キーが存在しない場合やString型でない場合、その位置にはNilが格納されます。
- 時間計算量: O(N) ただし N は取得するキーの数。
- 構文:
4.4 APPEND
指定したキーの文字列値の末尾に文字列を追記します。
- 構文:
APPEND key value - 説明: キーが存在しない場合、新しいキーを作成し、値をその初期値として設定します(SETと同じ動作)。キーが存在し、値がString型以外の場合、エラーになります。
- 使用例:
APPEND mykey " World"(mykey の値が “Hello” なら “Hello World” になります) - 戻り値: 追記後の文字列の長さ。
- 時間計算量: O(N) ただし N は追記する文字列の長さ。String値のサイズによっては再割り当てが発生し、遅くなる場合があります。
4.5 STRLEN
指定したキーの文字列値の長さを取得します。
- 構文:
STRLEN key - 説明: キーが存在しない場合は0を返します。String型以外の場合はエラーになります。
- 使用例:
STRLEN mykey - 戻り値: 文字列値の長さ(バイト単位)。
- 時間計算量: O(1)
4.6 INCR / DECR / INCRBY / DECRBY
キーに格納されている値を数値として扱い、増減させるコマンドです。主にカウンターとして使用されます。
- INCR: キーの値を1増やします。
- 構文:
INCR key - 説明: キーが存在しない場合、値を0として扱い、1に設定します。キーの値が整数として解釈できない場合や、大きすぎる/小さすぎる整数の場合、エラーになります。
- 使用例:
INCR visitor_count - 戻り値: 増減後の新しい値。
- 時間計算量: O(1)
- 構文:
- DECR: キーの値を1減らします。
- 構文:
DECR key - 説明:
INCRと同様ですが、1減算します。 - 使用例:
DECR remaining_items - 戻り値: 増減後の新しい値。
- 時間計算量: O(1)
- 構文:
- INCRBY: キーの値を指定した増分だけ増やします。
- 構文:
INCRBY key increment - 説明:
incrementは整数値です。INCRの汎用版です。 - 使用例:
INCRBY score:user:1 100(ユーザー1のスコアを100点増やす) - 戻り値: 増減後の新しい値。
- 時間計算量: O(1)
- 構文:
- DECRBY: キーの値を指定した減分だけ減らします。
- 構文:
DECRBY key decrement - 説明:
decrementは整数値です。DECRの汎用版です。 - 使用例:
DECRBY stock:book:978-4834000018 5(本の在庫を5冊減らす) - 戻り値: 増減後の新しい値。
- 時間計算量: O(1)
- 構文:
- INCRBYFLOAT: キーの値を指定した増分だけ増やします(浮動小数点数)。
- 構文:
INCRBYFLOAT key increment - 説明:
incrementは浮動小数点数です。 - 使用例:
INCRBYFLOAT balance:user:1 10.50 - 戻り値: 増減後の新しい値(文字列として)。
- 時間計算量: O(1)
- 構文:
これらのコマンドは、複数のクライアントから同時に実行されても安全なアトミック操作です。競合状態を気にすることなくカウンターを実装できます。
4.7 GETRANGE / SETRANGE
文字列の一部を取得(GETRANGE)したり、一部を上書き(SETRANGE)したりするコマンドです。
- GETRANGE:
- 構文:
GETRANGE key start end - 説明: 指定したキーの文字列の、
startからendまでの範囲(インデックスは0から始まります)を取得します。負のインデックスも使用でき、-1は最後の文字、-2は最後から2番目の文字を表します。範囲が文字列の長さを超える場合、存在する部分だけが返されます。 - 使用例:
- 文字列の最初の5文字を取得:
GETRANGE mykey 0 4 - 文字列の最後の5文字を取得:
GETRANGE mykey -5 -1 - 文字列全体を取得:
GETRANGE mykey 0 -1(GETと同じ)
- 文字列の最初の5文字を取得:
- 戻り値: 指定した範囲の部分文字列。
- 時間計算量: O(N) ただし N は取得する文字列の長さ。
- 構文:
- SETRANGE:
- 構文:
SETRANGE key offset value - 説明: 指定したキーの文字列の、
offsetの位置から、指定したvalueで文字列を上書きします。キーが存在しない場合、キーが作成され、値が0で埋められた後、valueがoffsetから書き込まれます。指定したオフセットが現在の文字列の長さより大きい場合、オフセットまでの間は0バイトで埋められます。 - 使用例:
SETRANGE mykey 6 "Redis"(mykey が “Hello World” なら “Hello Redis” になります) - 戻り値: 変更後の文字列の長さ。
- 時間計算量: O(N) ただし N は書き込む文字列の長さ。オフセットが大きい場合、追加のゼロ埋め処理が発生するため、文字列が長くなるほどコストがかかります。
- 構文:
これらのコマンドは、大きなバイナリデータ(画像など)の一部を操作する際に役立ちます。
5. List (リスト) コマンド
List は順序付けされた文字列のコレクションです。キューやスタックの実装によく使われます。
5.1 LPUSH / RPUSH
リストの先頭(LPUSH)または末尾(RPUSH)に1つ以上の要素を追加します。
- LPUSH:
- 構文:
LPUSH key element [element ...] - 説明: リストの左側(先頭)に指定した要素を順番に追加します。複数の要素を指定した場合、指定した順序でリストの先頭に追加されます(つまり、引数で最後に指定した要素が新しいリストの先頭になります)。キーが存在しない場合、新しいリストが作成されます。キーが存在し、String型以外の場合、エラーになります。
- 使用例:
LPUSH mylist "world",LPUSH mylist "hello"(mylist は [“hello”, “world”] になります),LPUSH newlist A B C(newlist は [“C”, “B”, “A”] になります) - 戻り値: Push操作後のリストの長さ。
- 時間計算量: O(N) ただし N は追加する要素の数。先頭への追加は常に O(1) ですが、引数解析のコストがあります。
- 構文:
- RPUSH:
- 構文:
RPUSH key element [element ...] - 説明: リストの右側(末尾)に指定した要素を順番に追加します。複数の要素を指定した場合、指定した順序でリストの末尾に追加されます。キーが存在しない場合、新しいリストが作成されます。
- 使用例:
RPUSH mylist "hello",RPUSH mylist "world"(mylist は [“hello”, “world”] になります),RPUSH newlist A B C(newlist は [“A”, “B”, “C”] になります) - 戻り値: Push操作後のリストの長さ。
- 時間計算量: O(N) ただし N は追加する要素の数。末尾への追加は常に O(1) ですが、引数解析のコストがあります。
- 構文:
LPUSH/RPUSHは、キュー(LPUSHでenqueue, RPOPでdequeue)やスタック(LPUSHでpush, LPOPでpop または RPUSHでpush, RPOPでpop)の基本操作として利用されます。
5.2 LPOP / RPOP
リストの先頭(LPOP)または末尾(RPOP)から要素を1つ取り出し、リストから削除します。
- LPOP:
- 構文:
LPOP key [count] - 説明: リストの左側(先頭)から要素を1つ(または指定した
count数だけ)取り出します。取り出された要素はリストから削除されます。キーが存在しない場合、Nil応答を返します。 - 使用例:
LPOP mylist,LPOP mylist 2(先頭から2つ取り出す) - 戻り値: 取り出した要素(count 指定がない場合)、または要素のリスト(count 指定がある場合)。リストが空またはキーが存在しない場合は Nil応答。
- 時間計算量: O(N) ただし N は取り出す要素の数 (count)。要素1つの取り出しは O(1)。
- 構文:
- RPOP:
- 構文:
RPOP key [count] - 説明: リストの右側(末尾)から要素を1つ(または指定した
count数だけ)取り出します。取り出された要素はリストから削除されます。キーが存在しない場合、Nil応答を返します。 - 使用例:
RPOP mylist,RPOP mylist 3(末尾から3つ取り出す) - 戻り値: 取り出した要素(count 指定がない場合)、または要素のリスト(count 指定がある場合)。リストが空またはキーが存在しない場合は Nil応答。
- 時間計算量: O(N) ただし N は取り出す要素の数 (count)。要素1つの取り出しは O(1)。
- 構文:
LPOP/RPOPは、リストをキューやスタックとして利用する際のdequeue/pop操作です。
5.3 LLEN
リストに格納されている要素の数を取得します。
- 構文:
LLEN key - 説明: 指定したキーが存在しない場合、0を返します。キーがList型以外の場合、エラーになります。
- 使用例:
LLEN mylist - 戻り値: リストの長さ。
- 時間計算量: O(1)
5.4 LRANGE
リストの指定した範囲の要素を取得します。
- 構文:
LRANGE key start stop - 説明: リストのインデックス
startからstopまでの要素を取得します。インデックスは0から始まります。負のインデックスも使用でき、-1は最後の要素、-2は最後から2番目の要素を表します。範囲がリストの長さを超える場合、存在する部分だけが返されます。startがstopより大きいインデックスを指定した場合、空のリストが返されます。LRANGE key 0 -1はリストの全ての要素を取得します。 - 使用例:
- 最初の3つの要素を取得:
LRANGE mylist 0 2 - リスト全体を取得:
LRANGE mylist 0 -1 - インデックス1からインデックス5までの要素を取得:
LRANGE mylist 1 5
- 最初の3つの要素を取得:
- 戻り値: 指定した範囲の要素のリスト。
- 時間計算量: O(S+N) ただし S は開始インデックス、N は範囲内の要素数。開始インデックスが小さい場合は O(N) と近似できます。リストの先頭に近い範囲の取得は比較的速いですが、末尾に近い範囲や非常に長いリストの中央付近の範囲を取得する場合は遅くなる可能性があります。
5.5 LINDEX
リストの指定したインデックスにある要素を取得します。
- 構文:
LINDEX key index - 説明:
indexは0から始まります。負のインデックスも使用できます。指定したインデックスが存在しない場合(リストの範囲外)、Nil応答を返します。 - 使用例:
LINDEX mylist 0(先頭の要素を取得),LINDEX mylist -1(末尾の要素を取得) - 戻り値: 指定したインデックスの要素、またはNil応答。
- 時間計算量: O(N) ただし N はインデックスの絶対値。リストの中央付近や末尾の要素を取得する場合は遅くなります。
5.6 LSET
リストの指定したインデックスの要素を新しい値で置き換えます。
- 構文:
LSET key index value - 説明: 指定した
indexがリストの範囲外の場合、エラーになります。 - 使用例:
LSET mylist 0 "first element" - 戻り値: OK (成功時)。エラー発生時はエラー応答。
- 時間計算量: O(N) ただし N はリストの長さ。インデックスが先頭または末尾に近い場合は O(1) となります。
5.7 LINSERT
リストの指定した要素の前または後ろに新しい要素を挿入します。
- 構文:
LINSERT key BEFORE|AFTER pivot value - 説明: リスト内の要素
pivotを探し、その前 (BEFORE) または後ろ (AFTER) にvalueを挿入します。pivotが見つからない場合、操作は行われず-1を返します。キーが存在しない場合、操作は行われず0を返します。 - 使用例:
LINSERT mylist AFTER "hello" "world"([“hello”, “world”, “goodbye”] のリストで “hello” の後ろに “world” を挿入すると [“hello”, “world”, “world”, “goodbye”] になります) - 戻り値: 挿入操作後のリストの長さ。
pivotが見つからない場合は-1。キーが存在しない場合は0。 - 時間計算量: O(N) ただし N はリストの長さ。
pivotが先頭または末尾に近い場合は O(1) となります。
5.8 LREM
リストから指定した値を持つ要素を削除します。
- 構文:
LREM key count value - 説明: リストから
valueと等しい要素を削除します。countの値によって削除方法が変わります。count > 0: リストの先頭からvalueと等しい要素を最大count個削除します。count < 0: リストの末尾からvalueと等しい要素を最大abs(count)個削除します。count = 0: リスト内の全てのvalueと等しい要素を削除します。
- 使用例:
- リストの先頭から最初の “apple” を削除:
LREM mylist 1 "apple" - リストの末尾から最後の “banana” を削除:
LREM mylist -1 "banana" - リスト内の全ての “orange” を削除:
LREM mylist 0 "orange"
- リストの先頭から最初の “apple” を削除:
- 戻り値: 削除された要素の数。
- 時間計算量: O(N) ただし N はリストの長さ。
5.9 LTRIM
リストを指定した範囲にトリム(切り詰め)します。指定した範囲外の要素は削除されます。
- 構文:
LTRIM key start stop - 説明:
LRANGEと同じインデックス指定ですが、こちらは範囲内の要素を残し、それ以外の要素を削除します。リストを固定長に保ちたい場合などに利用します。 - 使用例:
- リストの最初の100要素だけを残す:
LTRIM mylist 0 99 - リストの末尾10要素だけを残す:
LTRIM mylist -10 -1
- リストの最初の100要素だけを残す:
- 戻り値: OK (成功時)。
- 時間計算量: O(N) ただし N はトリムされる要素の数。
5.10 BLPOP / BRPOP (ブロッキング操作)
リストの先頭(BLPOP)または末尾(BRPOP)から要素を取り出しますが、リストが空の場合は、指定したタイムアウト時間、要素が追加されるまでブロックして待機します。
- BLPOP:
- 構文:
BLPOP key [key ...] timeout - 説明: 複数のリストキーを指定できます。指定した順序で各リストの先頭から要素を取得を試みます。最初の空でないリストから要素を取得し、その要素と元のキー名を返します。指定した全てのリストが空の場合、
timeout(秒)だけブロックします。timeoutを0にすると、要素が利用可能になるまで無限にブロックします。 - 使用例:
BLPOP tasks:high tasks:low 0(high優先、両方空なら無限待機) - 戻り値: 2要素のリスト: 最初の要素は要素が取り出されたキー名、2番目の要素は取り出された要素。タイムアウトした場合、Nil応答。
- 時間計算量: O(N) ただし N は指定されたキーの数。リストからの要素取り出しは O(1) です。
- 構文:
- BRPOP:
- 構文:
BRPOP key [key ...] timeout - 説明:
BLPOPと同様ですが、末尾から要素を取り出します。 - 使用例:
BRPOP queue:messages 5(queue:messages から要素を取得、空なら5秒待機) - 戻り値:
BLPOPと同様。 - 時間計算量: O(N) ただし N は指定されたキーの数。リストからの要素取り出しは O(1) です。
- 構文:
これらのブロッキングコマンドは、メッセージキューやタスクキューの実装において、コンシューマ(worker)が新しいタスクが投入されるのを効率的に待機するために非常に重要です。ポーリング(定期的にLPOPを呼び出して確認)に比べて、サーバーとクライアント双方の負荷を軽減できます。
6. Set (セット) コマンド
Set は順序を持たないユニークな要素の集合です。重複を許容しないコレクションや、集合演算に利用します。
6.1 SADD
セットに1つ以上の要素を追加します。
- 構文:
SADD key member [member ...] - 説明: 指定した要素をセットに追加します。既に追加されている要素は無視されます。キーが存在しない場合、新しいセットが作成されます。キーが存在し、Set型以外の場合、エラーになります。
- 使用例:
SADD myset "apple" "banana",SADD myset "apple"(2回目の “apple” は無視される) - 戻り値: 新たに追加された要素の数。
- 時間計算量: O(N) ただし N は追加する要素の数。個々の要素の追加は平均 O(1)。
6.2 SMEMBERS
セットに格納されている全ての要素を取得します。
- 構文:
SMEMBERS key - 説明: セット内の全ての要素をリストとして返します。セットなので順序は保証されません。キーが存在しない場合、空のセットを返します。キーがSet型以外の場合、エラーになります。
- 使用例:
SMEMBERS myset - 戻り値: セットの全ての要素のリスト。
- 時間計算量: O(N) ただし N はセットの要素数。要素数が多いセットに対して実行すると、サーバーをブロックする可能性があります。大規模なセットを走査する場合は
SSCANを使用することを推奨します。
6.3 SISMEMBER
指定した要素がセットのメンバーであるかを確認します。
- 構文:
SISMEMBER key member - 説明: 要素が存在すれば1、存在しなければ0を返します。キーが存在しない場合も0を返します。
- 使用例:
SISMEMBER myset "apple" - 戻り値: 1 (メンバーである), 0 (メンバーでない、またはキーが存在しない)。
- 時間計算量: O(1)
6.4 SCARD
セットに格納されている要素の数(カーディナリティ)を取得します。
- 構文:
SCARD key - 説明: 指定したキーが存在しない場合、0を返します。
- 使用例:
SCARD myset - 戻り値: セットの要素数。
- 時間計算量: O(1)
6.5 SREM
セットから1つ以上の要素を削除します。
- 構文:
SREM key member [member ...] - 説明: 指定した要素をセットから削除します。セットに存在しない要素を指定しても無視されます。
- 使用例:
SREM myset "apple" "banana" - 戻り値: 実際に削除された要素の数。
- 時間計算量: O(N) ただし N は削除する要素の数。個々の要素の削除は平均 O(1)。
6.6 SPOP
セットからランダムに1つの要素を取り出し、セットから削除します。Redis 3.2以降では複数要素の取得も可能です。
- 構文:
SPOP key [count] - 説明: セットからランダムに要素を選択し、返却し、セットから削除します。
countを指定すると、ランダムに複数要素を選択し、削除します。 - 使用例:
SPOP myset(1つ取得),SPOP myset 3(3つ取得) - 戻り値: 取り出された要素(count 指定なし)、または要素のリスト(count 指定あり)。セットが空またはキーが存在しない場合はNil応答(count 指定なし)または空リスト(count 指定あり)。
- 時間計算量: O(N) ただし N は取り出す要素の数 (count)。要素1つの取り出しは O(1)。
6.7 SRANDMEMBER
セットからランダムに要素を1つ(または複数)取得しますが、セットから削除はしません。
- 構文:
SRANDMEMBER key [count] - 説明:
countを正の整数で指定すると、重複なくランダムにcount個の要素を返します。countを負の整数で指定すると、重複を許容してランダムにabs(count)個の要素を返します。 - 使用例:
SRANDMEMBER myset(1つ取得),SRANDMEMBER myset 5(重複なく5つ取得),SRANDMEMBER myset -10(重複を許容して10個取得) - 戻り値: ランダムに選ばれた要素(count 指定なし)、または要素のリスト(count 指定あり)。セットが空またはキーが存在しない場合はNil応答(count 指定なし)または空リスト(count 指定あり)。
- 時間計算量: O(N) ただし N は取得する要素の数 (count の絶対値)。要素1つの取得は O(1)。
6.8 集合演算コマンド: SUNION, SINTER, SDIFF
複数のセットに対して和集合、積集合、差集合の演算を行います。結果を新しいセットに格納するコマンドもあります (SUNIONSTORE, SINTERSTORE, SDIFFSTORE)。
- SUNION: 複数のセットの和集合を取得します。
- 構文:
SUNION key [key ...] - 説明: 指定された全てのセットの全ての要素を含む新しいセット(結果)を返します。
- 使用例:
SUNION set1 set2 set3 - 戻り値: 和集合の結果である要素のリスト。
- 時間計算量: O(N) ただし N は全ての入力セットの合計要素数。
- 構文:
- SINTER: 複数のセットの積集合を取得します。
- 構文:
SINTER key [key ...] - 説明: 指定された全てのセットに共通して含まれる要素からなる新しいセット(結果)を返します。
- 使用例:
SINTER set1 set2 - 戻り値: 積集合の結果である要素のリスト。
- 時間計算量: O(NM) 最悪の場合。一般的には O(N log N) 〜 O(NM) の間ですが、Redisの実装では、最も小さいセットをベースにすることで効率化を図っています。
- 構文:
- SDIFF: 最初のセットとそれ以外のセットの差集合を取得します。
- 構文:
SDIFF key [key ...] - 説明: 最初のセットに含まれる要素のうち、2番目以降のどのセットにも含まれない要素からなる新しいセット(結果)を返します。
- 使用例:
SDIFF set1 set2 set3(set1 に含まれるが set2 や set3 には含まれない要素) - 戻り値: 差集合の結果である要素のリスト。
- 時間計算量: O(N) ただし N は全ての入力セットの合計要素数。
- 構文:
- 集合演算結果の保存:
SUNIONSTORE destination key [key ...]: 和集合の結果をdestinationという新しいキーのセットに保存します。SINTERSTORE destination key [key ...]: 積集合の結果をdestinationという新しいキーのセットに保存します。SDIFFSTORE destination key [key ...]: 差集合の結果をdestinationという新しいキーのセットに保存します。- これらのコマンドは、結果をクライアントに返却する代わりにサーバーサイドで保存するため、特に結果セットが大きい場合にネットワーク転送量を減らせます。戻り値は結果セットの要素数です。時間計算量は元の集合演算と同じです。
集合演算は、ソーシャルグラフ(共通の友達、フォロー/フォロワー)、推薦システム、アクセス権限チェックなど、Setの得意とする強力な機能です。
7. Sorted Set (ソート済みセット / Zset) コマンド
Sorted Set は、セットと同様にユニークな要素の集合ですが、各要素に付与された「スコア」に基づいてソートされます。ランキングシステムなどに最適です。
7.1 ZADD
Sorted Set に1つ以上の要素(メンバー)とそれに対応するスコアを追加します。
- 構文:
ZADD key [NX|XX] [CH] [INCR] score member [score member ...] - 説明:
score: メンバーに関連付ける浮動小数点数。member: セットに追加する要素。- オプション:
NX: メンバーが存在しない場合にのみ追加します。XX: メンバーが存在する場合にのみスコアを更新します。CH: 戻り値を、追加・更新されたメンバー数ではなく、Sorted Set の変更(新規追加またはスコア更新)が行われたメンバーの総数にします。INCR: 指定したメンバーのスコアを、指定したスコア分だけ増加させます。この場合、メンバーは1つだけ指定します。ZINCRBYコマンドと同様の動作になります。
- 使用例:
- メンバーとスコアを追加:
ZADD myzset 100 "member1" 200 "member2" - スコアを更新または新規追加:
ZADD myzset 150 "member1"(member1 のスコアが 100 から 150 に更新) - スコアを増減させる (
INCRオプション):ZADD myzset INCR 50 "member1"(member1 のスコアが 150 から 200 に増加)
- メンバーとスコアを追加:
- 戻り値: 新たに追加されたメンバーの数(CH オプションがない場合)。CH オプションがある場合は、追加または更新されたメンバーの総数。INCR オプションがある場合は、新しいスコア(文字列)。
- 時間計算量: O(M*log(N)) ただし N は Sorted Set の要素数、M は追加するメンバーの数。個々のメンバーの追加/更新は O(log(N))。
7.2 ZRANGE / ZREVRANGE
Sorted Set のメンバーをスコアの昇順(ZRANGE)または降順(ZREVRANGE)で、指定した順位の範囲で取得します。
- ZRANGE:
- 構文:
ZRANGE key start stop [WITHSCORES] - 説明: スコア昇順で、
startからstopまでの順位(インデックスは0から始まります)のメンバーを取得します。負のインデックスも使用できます。WITHSCORESオプションを付けると、メンバーと共にスコアも取得できます。 - 使用例:
- スコア昇順で最初の3メンバーを取得:
ZRANGE myzset 0 2 - スコア昇順で全てのメンバーを取得:
ZRANGE myzset 0 -1 - スコア付きで取得:
ZRANGE myzset 0 -1 WITHSCORES
- スコア昇順で最初の3メンバーを取得:
- 戻り値: 指定した範囲のメンバーのリスト。WITHSCORES オプションがある場合は [member, score, member, score, …] という形式のリスト。
- 時間計算量: O(log(N)+M) ただし N は Sorted Set の要素数、M は範囲内の要素数。
- 構文:
- ZREVRANGE:
- 構文:
ZREVRANGE key start stop [WITHSCORES] - 説明: スコア降順で、
startからstopまでの順位のメンバーを取得します。ランキング表示などによく使われます。 - 使用例:
ZREVRANGE myzset 0 9 WITHSCORES(スコア降順で上位10メンバーをスコア付きで取得) - 戻り値: ZRANGE と同様ですが、順序が逆になります。
- 時間計算量: O(log(N)+M) ただし N は Sorted Set の要素数、M は範囲内の要素数。
- 構文:
7.3 ZRANGEBYSCORE / ZREVRANGEBYSCORE
Sorted Set のメンバーを、指定したスコアの範囲で取得します。
- ZRANGEBYSCORE:
- 構文:
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] - 説明: スコア昇順で、スコアが
min以上max以下のメンバーを取得します。minおよびmaxの指定には以下の記法が使えます。100: スコア100を含む(100: スコア100を含まない(より大きい)-inf: 最小スコア(マイナス無限)+inf: 最大スコア(プラス無限)LIMIT offset count: 取得する結果を、オフセットと件数で制限できます(ページネーションなど)。
- 使用例:
ZRANGEBYSCORE myzset 0 100,ZRANGEBYSCORE myzset (100 +inf WITHSCORES LIMIT 0 10(スコア100より大きく、無限大以下のメンバーから最初の10件をスコア付きで取得) - 戻り値: 指定したスコア範囲のメンバーのリスト。WITHSCORES オプションがある場合はスコアも含まれます。
- 時間計算量: O(log(N)+M) ただし N は Sorted Set の要素数、M は取得する要素数。
- 構文:
- ZREVRANGEBYSCORE:
- 構文:
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count] - 説明: スコア降順で、スコアが
max以下min以上のメンバーを取得します。引数のmaxとminの順番が逆になる点に注意してください。 - 使用例:
ZREVRANGEBYSCORE myzset +inf 100 WITHSCORES(スコア無限大から100までのメンバーをスコア降順でスコア付き取得) - 戻り値: ZRANGEBYSCORE と同様ですが、順序が逆になります。
- 時間計算量: O(log(N)+M) ただし N は Sorted Set の要素数、M は取得する要素数。
- 構文:
7.4 ZCARD
Sorted Set に格納されているメンバーの数(カーディナリティ)を取得します。
- 構文:
ZCARD key - 説明: 指定したキーが存在しない場合は0を返します。
- 使用例:
ZCARD myzset - 戻り値: Sorted Set のメンバー数。
- 時間計算量: O(1)
7.5 ZCOUNT
指定したスコア範囲内のメンバーの数をカウントします。
- 構文:
ZCOUNT key min max - 説明: スコアが
min以上max以下のメンバー数を返します。minとmaxの指定方法はZRANGEBYSCOREと同様です。 - 使用例:
ZCOUNT myzset 0 100(スコア0以上100以下のメンバー数) - 戻り値: スコア範囲内のメンバー数。
- 時間計算量: O(log(N)+M) ただし N は Sorted Set の要素数、M はスコア範囲内の要素数。スコア範囲が狭い場合は O(log(N)) に近くなります。
7.6 ZRANK / ZREVRANK
指定したメンバーの、スコア昇順(ZRANK)または降順(ZREVRANK)での順位(0から始まるインデックス)を取得します。
- ZRANK:
- 構文:
ZRANK key member - 説明: スコア昇順でのメンバーの順位を返します。メンバーが存在しない場合、Nil応答を返します。
- 使用例:
ZRANK myzset "member1" - 戻り値: メンバーの順位、またはNil応答。
- 時間計算量: O(log(N)) ただし N は Sorted Set の要素数。
- 構文:
- ZREVRANK:
- 構文:
ZREVRANK key member - 説明: スコア降順でのメンバーの順位を返します。
- 使用例:
ZREVRANK myzset "member1"(ランキングで何位かを知りたい場合に利用) - 戻り値: メンバーの順位、またはNil応答。
- 時間計算量: O(log(N)) ただし N は Sorted Set の要素数。
- 構文:
7.7 ZSCORE
指定したメンバーのスコアを取得します。
- 構文:
ZSCORE key member - 説明: メンバーが存在しない場合、Nil応答を返します。
- 使用例:
ZSCORE myzset "member1" - 戻り値: メンバーのスコア(文字列として)、またはNil応答。
- 時間計算量: O(1)
7.8 ZREM
Sorted Set から1つ以上のメンバーを削除します。
- 構文:
ZREM key member [member ...] - 説明: 指定したメンバーをセットから削除します。セットに存在しないメンバーを指定しても無視されます。
- 使用例:
ZREM myzset "member1" "member2" - 戻り値: 実際に削除されたメンバーの数。
- 時間計算量: O(M*log(N)) ただし N は Sorted Set の要素数、M は削除するメンバーの数。個々のメンバーの削除は O(log(N))。
7.9 ZINCRBY
Sorted Set の指定したメンバーのスコアを指定した値だけ増加させます(減少させる場合は負の値を指定)。
- 構文:
ZINCRBY key increment member - 説明: メンバーが存在しない場合、スコア0で追加された後、指定した値だけ増加します。
- 使用例:
ZINCRBY myzset 50 "member1"(“member1” のスコアを50点増加) - 戻り値: 更新後のメンバーのスコア(文字列として)。
- 時間計算量: O(log(N)) ただし N は Sorted Set の要素数。
7.10 集合演算コマンド: ZUNIONSTORE, ZINTERSTORE
複数のSorted Set の和集合(ZUNIONSTORE)または積集合(ZINTERSTORE)を計算し、結果を新しいSorted Set に格納します。
- ZUNIONSTORE:
- 構文:
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX] - 説明: 指定した
numkeys個の入力キーのSorted Set の和集合を計算し、結果をdestinationに保存します。結果のスコアは、同じメンバーが複数の入力セットに存在する場合、デフォルトではそれぞれのスコアの合計になります (AGGREGATE SUM)。WEIGHTS: 各入力セットのスコアに乗算する重みを指定します。AGGREGATE: 複数のセットに同じメンバーが存在する場合のスコアの計算方法を指定します (SUM(合計),MIN(最小値),MAX(最大値))。
- 使用例:
ZUNIONSTORE resultzset 2 zset1 zset2 WEIGHTS 1 2 AGGREGATE MAX(zset1 と zset2 の和集合を計算し、zset1 のスコアは1倍、zset2 のスコアは2倍し、同じメンバーの場合は最大スコアを採用して resultzset に保存) - 戻り値: 結果のSorted Set に格納されたメンバー数。
- 時間計算量: O(N + M log M) ただし N は全ての入力セットの合計要素数、M は結果のセットの要素数。
- 構文:
- ZINTERSTORE:
- 構文:
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX] - 説明: 指定した
numkeys個の入力キーのSorted Set の積集合を計算し、結果をdestinationに保存します。積集合のメンバーは、全ての入力セットに共通して含まれるメンバーです。スコアの計算方法はZUNIONSTOREと同様です。 - 使用例:
ZINTERSTORE commonzset 2 zset1 zset2 AGGREGATE SUM(zset1 と zset2 の積集合を計算し、スコアはそれぞれの合計として commonzset に保存) - 戻り値: 結果のSorted Set に格納されたメンバー数。
- 時間計算量: O(N + M log M) ただし N は最も小さい入力セットの要素数、K は入力セットの数、M は結果のセットの要素数。
- 構文:
これらのストアコマンドは、複数のSorted Set を組み合わせた複雑なランキングや集計を行う際に非常に便利です。
8. Hash (ハッシュ) コマンド
Hash は、フィールドと値のペアのコレクションを値として持つデータ構造です。単一のキーで、関連する複数の属性を管理できます。
8.1 HSET
ハッシュに1つ以上のフィールドと値のペアを設定します。フィールドが既に存在する場合、その値は上書きされます。
- 構文:
HSET key field value [field value ...] - 説明: 指定したフィールドに値を設定します。複数のフィールドと値を一度に設定できます。キーが存在しない場合、新しいハッシュが作成されます。キーが存在し、Hash型以外の場合、エラーになります。
- 使用例:
HSET user:1 name "Alice" age 30 city "Tokyo" - 戻り値: 新たに追加されたフィールドの数(Redis 4.0以降)。Redis 4.0未満では常に1(フィールドが存在しない場合)または0(フィールドが存在する場合)でした。
- 時間計算量: O(N) ただし N は設定するフィールドの数。個々のフィールドの設定は平均 O(1)。
8.2 HGET
ハッシュから指定したフィールドの値を取得します。
- 構文:
HGET key field - 説明: 指定したフィールドの値を取得します。キーやフィールドが存在しない場合、Nil応答を返します。
- 使用例:
HGET user:1 name - 戻り値: フィールドの値(文字列として)、またはNil応答。
- 時間計算量: O(1)
8.3 HMSET (非推奨) / HMGET
複数のフィールドの値を一度に設定(HMSET – 非推奨)したり、取得(HMGET)したりするコマンドです。
- HMSET:
- 構文:
HMSET key field1 value1 field2 value2 ...(非推奨) - 説明: HSET の複数フィールド版です。このコマンドは非推奨となり、HSET の可変長引数機能(HSET key field1 value1 field2 value2 …)に置き換えられました。 Redis 4.0以降を使用している場合は
HSETを使用してください。 - 戻り値: OK (常に成功時)。
- 時間計算量: O(N) ただし N は設定するフィールドの数。
- 構文:
- HMGET:
- 構文:
HMGET key field [field ...] - 説明: 複数のフィールド名を引数に取ります。
- 使用例:
HMGET user:1 name age - 戻り値: 指定したフィールドに対応する値のリスト。キーやフィールドが存在しない場合、その位置にはNilが格納されます。
- 時間計算量: O(N) ただし N は取得するフィールドの数。
- 構文:
8.4 HKEYS / HVALS / HGETALL
ハッシュに格納されている全てのフィールド名(HKEYS)、全ての値(HVALS)、または全てのフィールドと値のペア(HGETALL)を取得します。
- HKEYS:
- 構文:
HKEYS key - 説明: ハッシュ内の全てのフィールド名のリストを返します。キーが存在しない場合は空リスト。
- 使用例:
HKEYS user:1 - 戻り値: フィールド名のリスト。
- 時間計算量: O(N) ただし N はハッシュのフィールド数。フィールド数が多い場合にサーバーをブロックする可能性があります。大規模なハッシュを走査する場合は
HSCANを使用することを推奨します。
- 構文:
- HVALS:
- 構文:
HVALS key - 説明: ハッシュ内の全ての値のリストを返します。キーが存在しない場合は空リスト。
- 使用例:
HVALS user:1 - 戻り値: 値のリスト。
- 時間計算量: O(N) ただし N はハッシュのフィールド数。
- 構文:
- HGETALL:
- 構文:
HGETALL key - 説明: ハッシュ内の全てのフィールドと値のペアをリストとして返します。フィールドと値が交互に並んだ形式になります [field1, value1, field2, value2, …]。キーが存在しない場合は空リスト。
- 使用例:
HGETALL user:1 - 戻り値: フィールドと値のリスト。
- 時間計算量: O(N) ただし N はハッシュのフィールド数。HKEYS や HVALS と同様、フィールド数が多い場合に注意が必要です。
- 構文:
8.5 HDEL
ハッシュから1つ以上のフィールドを削除します。
- 構文:
HDEL key field [field ...] - 説明: 指定したフィールドをハッシュから削除します。ハッシュやフィールドが存在しない場合、無視されます。ハッシュから全てのフィールドが削除されると、キー自体も削除されます。
- 使用例:
HDEL user:1 age city - 戻り値: 実際に削除されたフィールドの数。
- 時間計算量: O(N) ただし N は削除するフィールドの数。個々のフィールドの削除は平均 O(1)。
8.6 HEXISTS
指定したフィールドがハッシュに存在するかどうかを確認します。
- 構文:
HEXISTS key field - 説明: フィールドが存在すれば1、存在しなければ0を返します。キーが存在しない場合も0を返します。
- 使用例:
HEXISTS user:1 email - 戻り値: 1 (フィールドが存在する), 0 (フィールドが存在しない、またはキーが存在しない)。
- 時間計算量: O(1)
8.7 HLEN
ハッシュに格納されているフィールドの数(要素数)を取得します。
- 構文:
HLEN key - 説明: 指定したキーが存在しない場合は0を返します。
- 使用例:
HLEN user:1 - 戻り値: ハッシュのフィールド数。
- 時間計算量: O(1)
8.8 HINCRBY / HINCRBYFLOAT
ハッシュの指定したフィールドの値を数値として扱い、増減させるコマンドです。
- HINCRBY: フィールドの値を指定した増分(整数)だけ増やします。
- 構文:
HINCRBY key field increment - 説明: フィールドが存在しない場合、値を0として扱い、incrementを加算した値に設定します。フィールドの値が整数として解釈できない場合、エラーになります。
- 使用例:
HINCRBY product:1:stats views 1(商品の閲覧数を1増やす) - 戻り値: 増減後の新しい値。
- 時間計算量: O(1)
- 構文:
- HINCRBYFLOAT: フィールドの値を指定した増分(浮動小数点数)だけ増やします。
- 構文:
HINCRBYFLOAT key field increment - 説明: フィールドの値が浮動小数点数として解釈できない場合、エラーになります。
- 使用例:
HINCRBYFLOAT user:1:balance -10.50(ユーザーの残高を10.50減らす) - 戻り値: 増減後の新しい値(文字列として)。
- 時間計算量: O(1)
- 構文:
これらのコマンドもアトミックであり、複数のクライアントからの同時操作でも安全です。
8.9 HSETNX
ハッシュの指定したフィールドがまだ存在しない場合にのみ、フィールドと値を設定します。
- 構文:
HSETNX key field value - 説明:
fieldが既にハッシュに存在する場合、操作は行われず、0を返します。フィールドが存在しない場合、fieldとvalueを設定し、1を返します。キーが存在しない場合、新しいハッシュを作成し、フィールドと値を設定します。 - 使用例:
HSETNX user:1 email "[email protected]"(ユーザー1のメールアドレスがまだ設定されていなければ設定) - 戻り値: 1 (フィールドが設定された), 0 (フィールドが既に存在した)。
- 時間計算量: O(1)
Hashは、RDBやAOFによる永続化において、効率的なメモリ使用を可能にする場合があります(ハッシュが一定数以上のフィールドを持つか、フィールド値が一定サイズより大きい場合に最適化されたデータ構造に変換されます)。
9. その他の重要コマンド
データ構造固有のコマンド以外にも、Redisサーバーの状態確認や管理、データベース操作に関する重要なコマンドがあります。
9.1 PING
サーバーが応答可能か確認します。
- 構文:
PING - 説明: サーバーが正常に動作していればPONGと応答します。接続問題の診断などに使われます。
- 使用例:
PING - 戻り値: PONG、またはエラー応答。
- 時間計算量: O(1)
9.2 ECHO
指定した文字列をそのまま応答として返します。
- 構文:
ECHO message - 説明: デバッグや接続テストに利用できます。
- 使用例:
ECHO "Hello Redis" - 戻り値: 指定したメッセージ。
- 時間計算量: O(N) ただし N はメッセージの長さ。
9.3 SELECT
現在接続しているクライアントのデータベースを選択します。
- 構文:
SELECT index - 説明: Redisはデフォルトで0から15までのデータベースをサポートしています(設定ファイルで変更可能)。クライアントは接続時にデフォルトのデータベース(通常0)に接続されます。
SELECTコマンドで他のデータベースに切り替えることができます。各データベースは独立しており、キーや値は共有されません。 - 使用例:
SELECT 1(データベース1に切り替える) - 戻り値: OK (成功時)。指定したインデックスが存在しない場合はエラー応答。
- 時間計算量: O(1)
9.4 FLUSHALL / FLUSHDB
現在接続しているクライアントのデータベース(FLUSHDB)またはサーバー上の全てのデータベース(FLUSHALL)の全てのキーを削除します。
- FLUSHDB:
- 構文:
FLUSHDB [ASYNC] - 説明: 現在選択されているデータベースの全てのキーを削除します。
ASYNCオプションを付けると、削除処理をバックグラウンドで行い、コマンド自体はすぐに完了します。デフォルトは同期削除です。 - 使用例:
FLUSHDB,FLUSHDB ASYNC - 戻り値: OK。
- 注意点: 全てのデータを削除するため、本番環境での実行は非常に慎重に行う必要があります。
- 構文:
- FLUSHALL:
- 構文:
FLUSHALL [ASYNC] - 説明: サーバー上の全てのデータベース(0からサポートされている最大インデックスまで)の全てのキーを削除します。
ASYNCオプションも利用可能です。 - 使用例:
FLUSHALL,FLUSHALL ASYNC - 戻り値: OK。
- 注意点: サーバー全体の全てのデータを削除するため、極めて危険なコマンドです。本番環境での実行は厳禁と考えるべきです。
- 構文:
10. トランザクション
Redisトランザクションは、複数のコマンドをまとめてアトミックに(全て成功するか、全て失敗するかのいずれか)実行する仕組みを提供します。ただし、リレーショナルデータベースのようなロールバック機能とは少し異なります。
トランザクションは以下のコマンドで構成されます。
- MULTI: トランザクションを開始します。このコマンド以降に送信されたコマンドは、すぐに実行されずキューに格納されます。
- EXEC: キューに格納された全てのコマンドを実行します。
- DISCARD: キューに格納された全てのコマンドを破棄し、トランザクションを中止します。
- WATCH:
EXECが呼び出されるまでの間に、指定したキーが他のクライアントによって変更されていないかを監視します。変更されていた場合、トランザクションは失敗(Nil応答)します。楽観的ロック(Optimistic Locking)の実装に使われます。
トランザクションの基本的な流れ:
WATCH key [key ...]で監視するキーを指定(必要に応じて)。MULTIを実行してトランザクションを開始。- 実行したいコマンドを順番に送信。これらのコマンドはキューに格納されるだけで、すぐには実行されません(応答は
QUEUEDとなります)。 EXECを実行。キューに格納された全てのコマンドが順番に実行されます。EXECの戻り値は、キュー内の各コマンドの実行結果のリストになります。
トランザクションの特性:
- アトミック性:
EXECが実行されると、キュー内の全てのコマンドが他のクライアントのコマンドに割り込まれることなく、順番に実行されます。 - エラーハンドリング:
MULTIとEXECの間に構文エラーのあるコマンドがあった場合、EXEC実行時にエラーが返され、トランザクション全体が失敗します。- コマンド自体は正しいが、実行時エラー(例: String型のキーに対してリストコマンドを実行するなど)が発生した場合、そのコマンドはエラーとなりますが、トランザクション内の他のコマンドは実行を継続します。これはリレーショナルデータベースのロールバックとは異なる点です。
- WATCH と競合:
WATCHで監視しているキーがEXEC実行前に変更された場合、トランザクションはアボートされ、EXECはNil応答を返します。クライアントはNil応答を受け取ったら、通常は操作を最初からやり直します。
使用例:
redis
WATCH mykey
SET mykey "initial"
MULTI
GET mykey
SET mykey "new value"
EXEC
- もし
EXECが実行されるまでにmykeyが他のクライアントによって変更されなかった場合、EXECは["initial", OK]のリストを返します。 - もし
EXECが実行されるまでにmykeyが他のクライアントによって変更された場合、EXECは Nil を返します。クライアントはNilを受け取ったら、WATCHからやり直す必要があります。
トランザクションは、複数の関連する操作を安全かつ効率的に実行したい場合に役立ちます。
11. パブリッシュ/サブスクライブ (Pub/Sub)
RedisはPub/Sub(Publish/Subscribe)メッセージング機能も提供しています。これは、メッセージを送信する側(Publisher)と、特定のチャネルを購読する側(Subscriber)が直接通信するのではなく、Redisサーバーを介して間接的に通信するパターンです。
Pub/SubはFire and Forget(送信したら受信確認を待たない)モデルであり、メッセージの永続化や配信保証はありません。リアルタイムのイベント通知などに適しています。
主要なコマンドは以下の通りです。
- PUBLISH: 指定したチャネルにメッセージを送信します。
- 構文:
PUBLISH channel message - 説明: チャネルを購読している全てのクライアントにメッセージを送信します。
- 使用例:
PUBLISH news "Hello subscribers!" - 戻り値: メッセージを受信したクライアント(購読者)の数。
- 時間計算量: O(N+M) ただし N はパターンマッチングサブスクライバーの数、M は通常のチャネルサブスクライバーの数。
- 構文:
- SUBSCRIBE: 1つ以上のチャネルを購読します。
- 構文:
SUBSCRIBE channel [channel ...] - 説明: 指定したチャネルからのメッセージを受信するように設定します。このコマンドを実行したクライアントは、購読モードに入り、他のコマンドを受け付けなくなります(例外あり)。メッセージを受信すると、クライアントには
messageタイプ、チャネル名、メッセージ本体を含む特別なメッセージが送信されます。 - 使用例:
SUBSCRIBE chat:room:1 notifications - 戻り値: 購読が成功したことを示す確認応答。
- 構文:
- UNSUBSCRIBE: 1つ以上のチャネルの購読を解除します。
- 構文:
UNSUBSCRIBE [channel [channel ...]] - 説明: 指定したチャネルの購読を解除します。チャネルを指定しない場合、現在購読している全てのチャネルの購読を解除します。全てのチャネルの購読を解除すると、購読モードから抜けます。
- 使用例:
UNSUBSCRIBE chat:room:1,UNSUBSCRIBE(全ての購読解除) - 戻り値: 購読解除が成功したことを示す確認応答。
- 構文:
- PSUBSCRIBE / PUNSUBSCRIBE: パターンマッチングによる購読/購読解除です。
- PSUBSCRIBE pattern [pattern …]`: glob スタイルのパターンにマッチするチャネルからのメッセージを購読します。
- PUNSUBSCRIBE [pattern [pattern …]]`: 指定したパターンによる購読を解除します。
- 使用例:
PSUBSCRIBE news.*(news.xxx の全てのチャネルを購読),PUNSUBSCRIBE news.* - 戻り値: 購読/購読解除が成功したことを示す確認応答。パターンマッチングによるメッセージ受信時は、
pmessageタイプ、パターン、チャネル名、メッセージ本体を含むメッセージが送信されます。
Pub/Subは、リアルタイムチャット、イベント通知、キャッシュ無効化通知など、多数の受信者にメッセージを配信したい場合にシンプルで高速なソリューションを提供します。ただし、メッセージの信頼性が必要な場合は、ListやSorted Set を利用したキューイングパターンの方が適しています。
12. スクリプティング (Lua)
RedisはLuaスクリプトを実行する機能も提供しています。これにより、複数のRedisコマンドをサーバーサイドでアトミックに実行できます。これは、クライアント側で複数のコマンドを順次実行する際に発生するネットワーク遅延を削減し、競合状態を防ぐのに役立ちます。
主要なコマンドは以下の通りです。
- EVAL: 指定したLuaスクリプトを実行します。
- 構文:
EVAL script numkeys key [key ...] arg [arg ...] - 説明:
scriptは実行するLuaスクリプトです。numkeysはスクリプト内でアクセスするキーの数です。スクリプト内でアクセスするキーは、最初のnumkeys個の引数として渡す必要があり、Luaスクリプト内ではKEYSグローバル変数(テーブル)としてアクセスできます。それ以降の引数はARGVグローバル変数としてアクセスできます。Redisのスクリプトは、特別な設定をしない限り、単一のRedisインスタンス上でアトミックに実行されます。 - 使用例: Luaスクリプト:
return redis.call('GET', KEYS[1])コマンド:EVAL "return redis.call('GET', KEYS[1])" 1 mykey - 戻り値: スクリプトの
returnの結果。Redisの様々なデータ型(文字列、整数、配列、Nil)はLuaの値と相互変換されます。 - 時間計算量: スクリプト内で実行されるコマンドの時間計算量の合計に依存します。
- 構文:
- EVALSHA: キャッシュされたスクリプトのSHA1ハッシュを指定して実行します。
- 構文:
EVALSHA sha1 numkeys key [key ...] arg [arg ...] - 説明:
EVALと同様ですが、スクリプト本体の代わりにそのSHA1ハッシュを指定します。これにより、同じスクリプトを繰り返し実行する際のネットワーク転送量を削減できます。スクリプトはSCRIPT LOADコマンドで事前にキャッシュしておく必要があります。 - 戻り値:
EVALと同様。 - 時間計算量: スクリプト内で実行されるコマンドの時間計算量の合計に依存します。
- 構文:
スクリプティングは、Redisの基本コマンドを組み合わせた複雑なロジックをサーバーサイドで効率的かつ安全に実行するための強力な機能です。例えば、「キーが存在する場合にのみ値を更新し、その更新前の値を取得する」といった操作や、「複数のキーを操作し、全て成功した場合のみコミットする」といった操作をアトミックに実装できます。
13. 実践的な利用のヒント
基本コマンドを理解した上で、Redisをより効果的に利用するための実践的なヒントをいくつか紹介します。
- キー設計の重要性:
- 意味のある命名規則を使用しましょう(例:
objectType:id:attributeやuser:123:profile,product:456:views)。 - 長いキー名はメモリを消費しますが、非常に短すぎると衝突の可能性や可読性の低下を招きます。適切なバランスを見つけましょう。
- キー名の区切り文字には、慣習的にコロン(:)がよく使われます。
- 意味のある命名規則を使用しましょう(例:
KEYSコマンドの使用を避ける: 既に述べたように、KEYS *は本番環境では危険です。キーのパターンマッチング走査が必要な場合は、代わりにSCANコマンドとその関連コマンド (SSCAN,HSCAN,ZSCAN) を使用してください。これらはRedisサーバーをブロックせず、カーソルベースで少しずつキーを走査します。- パイプライン処理: 複数のコマンドを連続して実行したい場合、クライアントライブラリのパイプライン機能を利用しましょう。パイプラインを使うと、複数のコマンドを一度にサーバーに送信し、結果をまとめて受け取ることができます。これにより、コマンドごとのネットワークラウンドトリップによる遅延を削減し、スループットを向上させます。
- トランザクションの適切な使用:
MULTI/EXECはコマンドの実行をアトミックにしますが、Luaスクリプトのような複雑な条件分岐やループ処理はできません。複雑なアトミック操作が必要な場合は、Luaスクリプトを検討しましょう。 - データ構造の適切な選択: アプリケーションの要件に合わせて、最適なデータ構造を選択することがパフォーマンスとメモリ効率に直結します。
- 単純なキャッシュや設定値: String
- キュー、スタック、タイムライン: List
- 重複のないコレクション、集合演算: Set
- ランキング、スコアによる範囲検索: Sorted Set
- オブジェクト、複数の関連する属性: Hash
- メモリ使用量の監視: Redisはインメモリデータベースなので、メモリ使用量は重要なメトリクスです。
INFO memoryコマンドなどで監視し、メモリ不足によるSwap発生などを防ぎましょう。 - 永続化の理解: Redisはデフォルトでインメモリですが、RDB(ある時点でのスナップショット)やAOF(コマンドログ)による永続化機能を持ちます。データの重要度に応じて適切な永続化方法を設定しましょう。
- コマンドの複雑性 (時間計算量): 各コマンドのドキュメントには時間計算量(O記法)が記載されています。これは、そのコマンドがどれだけ計算コストがかかるかの指標です。特に O(N) や O(N log N) のコマンドを、要素数の多いキーに対して頻繁に実行すると、サーバーの応答速度に影響を与える可能性があるため注意が必要です。O(1) のコマンドを組み合わせるのが理想的です。
14. まとめ
この記事では、Redisの基本的なコマンドについて、主要なデータ構造(String, List, Set, Sorted Set, Hash)ごとに解説しました。加えて、共通コマンド、トランザクション、Pub/Sub、そしてスクリプティングの基礎にも触れ、さらに実践的な利用のヒントも紹介しました。
- String: シンプルなキー・バリュー、カウンター、部分文字列操作。
- List: キュー、スタック、タイムライン。先頭/末尾操作が高速。
- Set: 重複のないコレクション、高速な存在チェック、集合演算。
- Sorted Set: ランキング、スコアによるソートと範囲検索。
- Hash: オブジェクト表現、複数の関連データの管理。フィールドごとのアクセスが高速。
- 共通コマンド: キーの存在確認、削除、型確認、有効期限設定など。
- トランザクション: 複数のコマンドをアトミックに実行。
- Pub/Sub: リアルタイムメッセージング。
- スクリプティング: サーバーサイドでのアトミックな複雑処理。
これらのコマンドは、Redisを使いこなすための土台となります。まずはこれらの基本コマンドをredis-cliなどで実際に試してみることをお勧めします。
この記事で紹介したコマンドは、Redisが提供するコマンドのごく一部に過ぎません。しかし、これらはRedisの最も基本的な操作であり、様々なアプリケーションで頻繁に利用されるものです。これらのコマンドをしっかりと理解することで、Redisの強力な機能を活用し、より効率的でスケーラブルなアプリケーションを構築する基礎が築けます。
次のステップ:
- 各データ構造のより詳細なコマンドを学ぶ。
SCANコマンドによる安全なキー走査の方法を学ぶ。- Redisクライアントライブラリを使って、お好みのプログラミング言語からRedisを操作してみる。
- Redisのデータ永続化(RDB, AOF)やレプリケーション、クラスタリングといった運用・拡張に関するトピックを学ぶ。
Redisの世界へようこそ!基本コマンドをマスターし、ぜひその魅力を体験してください。