Redis 構築・運用に役立つコマンド集:効率的なデータ管理
Redis は、インメモリデータ構造ストアとして広く利用されており、高速なデータアクセスと柔軟なデータ構造が魅力です。キャッシュ、セッション管理、リアルタイム分析、メッセージキューなど、多岐にわたる用途で活用されています。本記事では、Redis の構築から運用まで、効率的なデータ管理に役立つコマンドを網羅的に解説します。基本的なコマンドから、パフォーマンスチューニング、トラブルシューティングに役立つコマンドまで、具体的なユースケースを交えながら、Redis を最大限に活用するための知識を深めていきましょう。
1. Redis の基礎と構築
Redis を効果的に活用するためには、その基礎を理解し、適切な環境を構築することが重要です。
1.1 Redis の基本概念
- インメモリデータストア: Redis はデータを RAM に格納するため、ディスクアクセスを伴う従来のデータベースと比較して、圧倒的に高速な読み書き性能を発揮します。
- キー・バリューストア: データはキーと値のペアで格納されます。キーは文字列、値は様々なデータ構造(文字列、ハッシュ、リスト、セット、ソート済みセット)を格納できます。
- データ構造の多様性: Redis は、文字列だけでなく、リスト、ハッシュ、セット、ソート済みセットといった様々なデータ構造をサポートしています。これにより、複雑なデータ構造を効率的に操作できます。
- 永続化: Redis は、インメモリデータストアでありながら、RDB スナップショットや AOF (Append Only File) ロギングといったメカニズムを通じて、データの永続化をサポートしています。
- ** Pub/Sub:** Redis は Pub/Sub モデルをサポートしており、メッセージングシステムとして利用できます。
- トランザクション: Redis は、複数のコマンドをまとめて実行できるトランザクションをサポートしています。
- Lua スクリプティング: Redis は Lua スクリプトを実行できるため、複雑なロジックを Redis サーバ内で実行できます。
1.2 Redis のインストール
Redis は、Linux、macOS、Windows など、様々なプラットフォームで利用できます。
-
Linux (Ubuntu):
bash
sudo apt update
sudo apt install redis-server -
macOS (Homebrew):
bash
brew update
brew install redis -
Windows: 公式サイトからインストーラをダウンロードして実行します。
インストール後、redis-server
コマンドで Redis サーバを起動します。デフォルトでは、ポート 6379 で接続を受け付けます。
1.3 Redis クライアント:
Redis サーバと通信するためには、Redis クライアントが必要です。Redis クライアントは、様々なプログラミング言語で利用できます。
- redis-cli (コマンドラインクライアント): Redis に付属しているコマンドラインクライアントです。手軽に Redis サーバを操作できます。
-
Python (redis-py):
“`python
import redisr = redis.Redis(host=’localhost’, port=6379, db=0)
r.set(‘foo’, ‘bar’)
print(r.get(‘foo’)) # Output: b’bar’
“` -
Java (Jedis):
“`java
import redis.clients.jedis.Jedis;public class RedisExample {
public static void main(String[] args) {
Jedis jedis = new Jedis(“localhost”, 6379);
jedis.set(“foo”, “bar”);
System.out.println(jedis.get(“foo”)); // Output: bar
jedis.close();
}
}
“` -
Node.js (ioredis):
“`javascript
const Redis = require(‘ioredis’);
const redis = new Redis();redis.set(‘foo’, ‘bar’);
redis.get(‘foo’).then(function (result) {
console.log(result); // Output: bar
});
“`
1.4 Redis の設定ファイル (redis.conf)
Redis の設定は、redis.conf
ファイルで行います。主な設定項目は以下の通りです。
- bind: Redis サーバがリッスンする IP アドレス。デフォルトは
127.0.0.1
です。外部からの接続を許可する場合は0.0.0.0
に変更します。 - port: Redis サーバがリッスンするポート。デフォルトは
6379
です。 - requirepass: Redis サーバへの接続に必要なパスワードを設定します。セキュリティのため、必ず設定することを推奨します。
- maxmemory: Redis が使用できる最大メモリ容量を設定します。メモリが不足すると、設定された eviction policy に従ってデータが削除されます。
- maxmemory-policy: メモリが不足した場合のデータ削除ポリシーを設定します。
volatile-lru
: 有効期限が設定されているキーの中で、最も最近使用されていないものを削除します。allkeys-lru
: 全てのキーの中で、最も最近使用されていないものを削除します。volatile-ttl
: 有効期限が設定されているキーの中で、有効期限が最も近いものを削除します。noeviction
: 削除を行わず、書き込み操作をエラーにします。
- appendonly: AOF ロギングを有効にするかどうかを設定します。
- appendfsync: AOF ファイルへの書き込み頻度を設定します。
always
: 毎回書き込みます。最も安全ですが、パフォーマンスが低下します。everysec
: 1秒ごとに書き込みます。デフォルトの設定で、安全とパフォーマンスのバランスが取れています。no
: OS に書き込みを任せます。最も高速ですが、データ損失のリスクが高まります。
- save: RDB スナップショットの作成条件を設定します。
設定ファイルを変更した後、Redis サーバを再起動して変更を反映させる必要があります。
2. 基本的なデータ操作コマンド
Redis を利用する上で、基本的なデータ操作コマンドは必須の知識です。ここでは、文字列、ハッシュ、リスト、セット、ソート済みセットの各データ構造に対する基本的なコマンドを解説します。
2.1 文字列 (String)
-
SET key value [EX seconds|PX milliseconds|KEEPTTL] [NX|XX]: キーに値を設定します。
EX seconds
: キーの有効期限を秒単位で設定します。PX milliseconds
: キーの有効期限をミリ秒単位で設定します。KEEPTTL
: 既存の有効期限を保持します。NX
: キーが存在しない場合のみ設定します。XX
: キーが存在する場合のみ設定します。
redis
SET mykey "Hello"
SET mykey "World" EX 10 # 10秒後に期限切れ
SET mykey "New Value" NX # キーが存在しない場合のみ設定 -
GET key: キーに対応する値を取得します。キーが存在しない場合は
nil
を返します。redis
GET mykey # "World" -
GETSET key value: キーに対応する値を新しい値に設定し、古い値を返します。
redis
GETSET mykey "New World" # "World"
GET mykey # "New World" -
MSET key value [key value …]: 複数のキーに値を設定します。
redis
MSET key1 "Value 1" key2 "Value 2" -
MGET key [key …]: 複数のキーに対応する値を取得します。キーが存在しない場合は
nil
を返します。redis
MGET key1 key2 # ["Value 1", "Value 2"] -
INCR key: キーに対応する値を 1 インクリメントします。キーが存在しない場合は 0 として扱います。値は整数である必要があります。
redis
SET counter 10
INCR counter # 11 -
DECR key: キーに対応する値を 1 デクリメントします。キーが存在しない場合は 0 として扱います。値は整数である必要があります。
redis
DECR counter # 10 -
INCRBY key increment: キーに対応する値を指定された値だけインクリメントします。
redis
INCRBY counter 5 # 15 -
DECRBY key decrement: キーに対応する値を指定された値だけデクリメントします。
redis
DECRBY counter 3 # 12 -
APPEND key value: キーに対応する値に指定された文字列を追加します。
redis
SET message "Hello"
APPEND message " World" # 11 (文字列の長さ)
GET message # "Hello World" -
STRLEN key: キーに対応する文字列の長さを取得します。
redis
STRLEN message # 11
2.2 ハッシュ (Hash)
ハッシュは、キーの中にフィールドと値のペアを格納できるデータ構造です。
-
HSET key field value [field value …]: ハッシュの指定されたフィールドに値を設定します。
redis
HSET user:1 name "John Doe" age 30 -
HGET key field: ハッシュの指定されたフィールドの値を取得します。
redis
HGET user:1 name # "John Doe" -
HMSET key field value [field value …]: ハッシュの複数のフィールドに値を設定します。
redis
HMSET user:1 name "Jane Doe" age 25 city "New York" -
HMGET key field [field …]: ハッシュの複数のフィールドの値を取得します。
redis
HMGET user:1 name age # ["Jane Doe", "25"] -
HGETALL key: ハッシュの全てのフィールドと値を取得します。
redis
HGETALL user:1 # {"name": "Jane Doe", "age": "25", "city": "New York"} -
HDEL key field [field …]: ハッシュの指定されたフィールドを削除します。
redis
HDEL user:1 city -
HLEN key: ハッシュのフィールド数を取得します。
redis
HLEN user:1 # 2 -
HKEYS key: ハッシュの全てのフィールド名を取得します。
redis
HKEYS user:1 # ["name", "age"] -
HVALS key: ハッシュの全ての値を取得します。
redis
HVALS user:1 # ["Jane Doe", "25"] -
HEXISTS key field: ハッシュに指定されたフィールドが存在するかどうかを確認します。
redis
HEXISTS user:1 name # 1 (存在する)
HEXISTS user:1 city # 0 (存在しない) -
HINCRBY key field increment: ハッシュの指定されたフィールドの値を指定された値だけインクリメントします。フィールドが存在しない場合は 0 として扱います。
redis
HINCRBY user:1 age 5 # 30
2.3 リスト (List)
リストは、要素を順序付けて格納できるデータ構造です。
-
LPUSH key value [value …]: リストの先頭に要素を追加します。
redis
LPUSH mylist "world"
LPUSH mylist "hello" # mylist: ["hello", "world"] -
RPUSH key value [value …]: リストの末尾に要素を追加します。
redis
RPUSH mylist "!" # mylist: ["hello", "world", "!"] -
LPOP key: リストの先頭の要素を削除し、その値を返します。
redis
LPOP mylist # "hello" -
RPOP key: リストの末尾の要素を削除し、その値を返します。
redis
RPOP mylist # "!" -
LLEN key: リストの長さを取得します。
redis
LLEN mylist # 1 -
LRANGE key start stop: リストの指定された範囲の要素を取得します。
redis
LPUSH mylist "a" "b" "c" "d" "e"
LRANGE mylist 0 2 # ["e", "d", "c"]
LRANGE mylist -2 -1 # ["b", "a"] -
LINDEX key index: リストの指定されたインデックスの要素を取得します。
redis
LINDEX mylist 0 # "e" -
LSET key index value: リストの指定されたインデックスの要素を新しい値に設定します。
redis
LSET mylist 0 "f" # mylist: ["f", "d", "c", "b", "a"] -
LREM key count value: リストから指定された値の要素を削除します。
count > 0
: 先頭から指定された数の要素を削除します。count < 0
: 末尾から指定された数の要素を削除します。count = 0
: 全ての要素を削除します。
redis
LPUSH mylist "a" "b" "c" "a" "a"
LREM mylist 2 "a" # mylist: ["b", "c", "a"] -
LTRIM key start stop: リストを指定された範囲にトリムします。
redis
LTRIM mylist 1 2 # mylist: ["c"]
2.4 セット (Set)
セットは、重複を許さない要素の集合を格納できるデータ構造です。
-
SADD key member [member …]: セットに要素を追加します。
redis
SADD myset "hello"
SADD myset "world"
SADD myset "hello" # 重複は追加されない -
SMEMBERS key: セットの全ての要素を取得します。
redis
SMEMBERS myset # ["world", "hello"] -
SREM key member [member …]: セットから要素を削除します。
redis
SREM myset "hello" -
SISMEMBER key member: セットに指定された要素が存在するかどうかを確認します。
redis
SISMEMBER myset "world" # 1 (存在する)
SISMEMBER myset "hello" # 0 (存在しない) -
SCARD key: セットの要素数を取得します。
redis
SCARD myset # 1 -
SPOP key [count]: セットからランダムに要素を削除し、その値を返します。
redis
SPOP myset # "world" (ランダム) -
SRANDMEMBER key [count]: セットからランダムに要素を取得します。削除は行いません。
redis
SRANDMEMBER myset # "world" (ランダム)
SRANDMEMBER myset 2 # ["world", "hello"] (ランダム) -
SINTER key [key …]: 複数のセットの積集合を取得します。
redis
SADD set1 "a" "b" "c"
SADD set2 "b" "c" "d"
SINTER set1 set2 # ["b", "c"] -
SUNION key [key …]: 複数のセットの和集合を取得します。
redis
SUNION set1 set2 # ["a", "b", "c", "d"] -
SDIFF key [key …]: 複数のセットの差集合を取得します。
redis
SDIFF set1 set2 # ["a"]
2.5 ソート済みセット (Sorted Set)
ソート済みセットは、スコアに基づいて要素をソートした集合を格納できるデータ構造です。
-
ZADD key [NX|XX] [CH] [INCR] score member [score member …]: ソート済みセットに要素を追加します。
NX
: キーが存在しない場合のみ追加します。XX
: キーが存在する場合のみ追加します。CH
: スコアが変更された要素の数を返します。INCR
: 要素のスコアをインクリメントします。
redis
ZADD myzset 1 "one"
ZADD myzset 2 "two"
ZADD myzset 3 "three" -
ZRANGE key start stop [WITHSCORES]: ソート済みセットの指定された範囲の要素をスコアの低い順に取得します。
WITHSCORES
: スコアも一緒に取得します。
redis
ZRANGE myzset 0 -1 # ["one", "two", "three"]
ZRANGE myzset 0 -1 WITHSCORES # ["one", "1", "two", "2", "three", "3"] -
ZREVRANGE key start stop [WITHSCORES]: ソート済みセットの指定された範囲の要素をスコアの高い順に取得します。
redis
ZREVRANGE myzset 0 -1 # ["three", "two", "one"] -
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]: ソート済みセットの指定されたスコア範囲の要素をスコアの低い順に取得します。
min
とmax
には、数値または-inf
(負の無限大)、+inf
(正の無限大) を指定できます。(min
や(max
のように、括弧で囲むことで、そのスコアを含めない範囲を指定できます。LIMIT offset count
: offset から count 個の要素を取得します。
redis
ZRANGEBYSCORE myzset 1 2 # ["one", "two"]
ZRANGEBYSCORE myzset (1 2 # ["two"]
ZRANGEBYSCORE myzset -inf +inf # ["one", "two", "three"] -
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]: ソート済みセットの指定されたスコア範囲の要素をスコアの高い順に取得します。
redis
ZREVRANGEBYSCORE myzset 2 1 # ["two", "one"] -
ZREM key member [member …]: ソート済みセットから要素を削除します。
redis
ZREM myzset "two" -
ZCARD key: ソート済みセットの要素数を取得します。
redis
ZCARD myzset # 2 -
ZSCORE key member: ソート済みセットの指定された要素のスコアを取得します。
redis
ZSCORE myzset "one" # "1" -
ZINCRBY key increment member: ソート済みセットの指定された要素のスコアをインクリメントします。
redis
ZINCRBY myzset 2 "one" # "3" -
ZRANK key member: ソート済みセットの指定された要素の順位をスコアの低い順に取得します。
redis
ZRANK myzset "one" # 0 -
ZREVRANK key member: ソート済みセットの指定された要素の順位をスコアの高い順に取得します。
redis
ZREVRANK myzset "one" # 1
3. Redis の永続化
Redis はインメモリデータストアですが、データの永続化をサポートしています。永続化には、RDB スナップショットと AOF ロギングの2つの方法があります。
3.1 RDB スナップショット
RDB スナップショットは、指定された間隔でメモリ上のデータをディスクに保存します。これは、データベースの完全なバックアップとなります。
-
SAVE: 現在のデータベースの状態をディスクに保存します。このコマンドはブロッキング操作であるため、大規模なデータベースではパフォーマンスに影響を与える可能性があります。
redis
SAVE -
BGSAVE: バックグラウンドでデータベースの状態をディスクに保存します。このコマンドはノンブロッキング操作であるため、サーバのパフォーマンスに影響を与えません。
redis
BGSAVE
RDB スナップショットの作成条件は、redis.conf
ファイルで設定できます。例えば、以下のように設定すると、5分(300秒)以内に1000個のキーが変更された場合、または15分(900秒)以内に10個のキーが変更された場合に、RDB スナップショットが作成されます。
save 300 1000
save 900 10
3.2 AOF (Append Only File) ロギング
AOF ロギングは、全ての書き込み操作をファイルに記録します。これにより、Redis サーバがクラッシュした場合でも、AOF ファイルを再生することでデータを復元できます。
- AOF ロギングを有効にするには、
redis.conf
ファイルでappendonly yes
を設定します。
appendonly yes
- AOF ファイルへの書き込み頻度は、
appendfsync
設定で制御できます。always
: 毎回書き込みます。最も安全ですが、パフォーマンスが低下します。everysec
: 1秒ごとに書き込みます。デフォルトの設定で、安全とパフォーマンスのバランスが取れています。no
: OS に書き込みを任せます。最も高速ですが、データ損失のリスクが高まります。
appendfsync everysec
-
AOF ファイルが肥大化した場合、
BGREWRITEAOF
コマンドを使用して AOF ファイルを最適化できます。redis
BGREWRITEAOF
3.3 RDB と AOF の選択
- RDB: データバックアップに適しています。高速な復元が可能ですが、最新のデータが失われる可能性があります。
- AOF: データ損失のリスクを最小限に抑えたい場合に適しています。RDB よりも復元に時間がかかる可能性があります。
一般的には、両方の永続化方法を組み合わせることで、安全性を高めることが推奨されます。
4. Redis の Pub/Sub
Redis は Pub/Sub モデルをサポートしており、メッセージングシステムとして利用できます。
-
PUBLISH channel message: 指定されたチャンネルにメッセージを送信します。
redis
PUBLISH mychannel "Hello, world!" -
SUBSCRIBE channel [channel …]: 指定されたチャンネルを購読します。
redis
SUBSCRIBE mychannel -
PSUBSCRIBE pattern [pattern …]: 指定されたパターンに一致するチャンネルを購読します。
redis
PSUBSCRIBE news.* -
UNSUBSCRIBE channel [channel …]: 指定されたチャンネルの購読を解除します。
redis
UNSUBSCRIBE mychannel -
PUNSUBSCRIBE pattern [pattern …]: 指定されたパターンに一致するチャンネルの購読を解除します。
redis
PUNSUBSCRIBE news.*
Pub/Sub は、リアルタイムチャット、イベント通知、メッセージキューイングなどの用途に活用できます。
5. Redis のトランザクション
Redis は、複数のコマンドをまとめて実行できるトランザクションをサポートしています。
-
MULTI: トランザクションを開始します。
redis
MULTI -
EXEC: トランザクションを実行します。
redis
EXEC -
DISCARD: トランザクションを破棄します。
redis
DISCARD -
WATCH key [key …]: トランザクションを実行する前に、指定されたキーが変更されていないか監視します。キーが変更された場合、トランザクションは失敗します。
redis
WATCH mykey
トランザクションを使用することで、複数のコマンドをアトミックに実行できます。
6. Redis のスクリプティング (Lua)
Redis は Lua スクリプトを実行できるため、複雑なロジックを Redis サーバ内で実行できます。
-
EVAL script numkeys key [key …] arg [arg …]: Lua スクリプトを実行します。
script
: Lua スクリプトの文字列。numkeys
: Lua スクリプトで使用するキーの数。key [key ...]
: Lua スクリプトで使用するキー。arg [arg ...]
: Lua スクリプトで使用する引数。
redis
EVAL "return redis.call('GET', KEYS[1])" 1 mykey -
SCRIPT LOAD script: Lua スクリプトをコンパイルし、キャッシュします。
redis
SCRIPT LOAD "return redis.call('GET', KEYS[1])" -
EVALSHA sha1 numkeys key [key …] arg [arg …]: キャッシュされた Lua スクリプトを実行します。
redis
EVALSHA <sha1> 1 mykey
Lua スクリプティングを使用することで、複雑なロジックを効率的に実行できます。
7. Redis の管理と監視
Redis の安定運用のためには、適切な管理と監視が不可欠です。
-
INFO [section]: Redis サーバの情報を取得します。
server
: サーバに関する情報。clients
: クライアントに関する情報。memory
: メモリに関する情報。persistence
: 永続化に関する情報。stats
: 統計情報。replication
: レプリケーションに関する情報。cpu
: CPU に関する情報。commandstats
: コマンド統計情報。cluster
: クラスタに関する情報。keyspace
: キー空間に関する情報。
redis
INFO memory -
CLIENT LIST: 接続されているクライアントの情報を取得します。
redis
CLIENT LIST -
CONFIG GET parameter: Redis の設定値を取得します。
redis
CONFIG GET maxmemory -
CONFIG SET parameter value: Redis の設定値を変更します。
redis
CONFIG SET maxmemory 1024MB -
SLOWLOG GET [number]: 遅延クエリログを取得します。
redis
SLOWLOG GET 10 -
FLUSHDB: 現在のデータベースの全てのキーを削除します。
redis
FLUSHDB -
FLUSHALL: 全てのデータベースの全てのキーを削除します。
redis
FLUSHALL -
SHUTDOWN [SAVE|NOSAVE]: Redis サーバを停止します。
SAVE
: 停止前にデータベースを保存します。NOSAVE
: 停止前にデータベースを保存しません。
redis
SHUTDOWN SAVE
これらのコマンドを活用することで、Redis サーバの状態を把握し、問題が発生した場合に迅速に対応できます。
8. Redis のパフォーマンスチューニング
Redis のパフォーマンスを最大限に引き出すためには、適切なチューニングが必要です。
- メモリ管理:
maxmemory
を適切に設定し、メモリ不足によるデータ削除を回避します。maxmemory-policy
をアプリケーションの要件に合わせて適切に設定します。
- データ構造の選択:
- 適切なデータ構造を選択することで、メモリ使用量とパフォーマンスを最適化できます。
- 例えば、大規模なセットを扱う場合は、ビットマップを使用することでメモリ使用量を削減できます。
- コマンドの最適化:
MGET
やMSET
などのバルクコマンドを使用することで、ネットワークラウンドトリップを削減できます。- Lua スクリプトを使用することで、複雑なロジックを Redis サーバ内で実行し、ネットワークオーバーヘッドを削減できます。
- 接続数の管理:
- 接続数が多すぎると、サーバの負荷が高まります。
maxclients
を適切に設定し、不要な接続を減らすようにします。
- 接続数が多すぎると、サーバの負荷が高まります。
- ネットワーク設定:
- ネットワーク遅延を最小限に抑えるために、Redis サーバとクライアントを同じネットワークに配置します。
- TCP Keep-Alive を有効にすることで、アイドル状態の接続を自動的に切断できます。
- AOF ロギング設定:
appendfsync
をeverysec
に設定することで、安全とパフォーマンスのバランスを取ります。
- ハードウェアの最適化:
- 高速な SSD を使用することで、RDB スナップショットや AOF ロギングのパフォーマンスを向上させることができます。
- 十分なメモリを搭載することで、Redis がメモリ不足になることを防ぎます。
9. Redis のトラブルシューティング
Redis で問題が発生した場合、以下の手順でトラブルシューティングを行います。
- ログの確認:
- Redis のログファイル (
redis-server.log
) を確認し、エラーメッセージや警告メッセージを探します。
- Redis のログファイル (
- INFO コマンドの実行:
INFO
コマンドを実行し、Redis サーバの状態を把握します。特に、memory
セクションやstats
セクションを重点的に確認します。
- SLOWLOG の確認:
SLOWLOG GET
コマンドを実行し、遅延クエリがないか確認します。
- CLIENT LIST の確認:
CLIENT LIST
コマンドを実行し、接続されているクライアントの状態を確認します。
- モニタリングツールの活用:
- Redis 専用のモニタリングツール (RedisInsight, Prometheus + Grafana) や、一般的なサーバモニタリングツール (Nagios, Zabbix) を活用して、Redis サーバの状態を継続的に監視します。
- コミュニティへの質問:
- Redis に関する質問は、Stack Overflow や Redis のメーリングリストなどのコミュニティで積極的に質問しましょう。
まとめ
本記事では、Redis の構築から運用まで、効率的なデータ管理に役立つコマンドを網羅的に解説しました。Redis の基礎知識、データ操作コマンド、永続化、Pub/Sub、トランザクション、スクリプティング、管理・監視、パフォーマンスチューニング、トラブルシューティングなど、幅広いトピックを網羅的に解説しました。
これらの知識を活用することで、Redis を最大限に活用し、アプリケーションのパフォーマンスとスケーラビリティを向上させることができます。ぜひ、本記事を参考に、Redis の活用に取り組んでみてください。