Redis

高性能なインメモリキーバリューストア。データ構造サーバー、キャッシュ、メッセージブローカーとして機能。豊富なデータ型とAtomic操作をサポート。

キャッシュデータベースNoSQLインメモリ高性能リアルタイムデータ構造Pub/Sub

Redis

Redisは、高性能なインメモリデータ構造ストアです。キャッシュ、データベース、メッセージブローカーとして使用され、豊富なデータ型とアトミック操作をサポートしています。

主な特徴

豊富なデータ構造

  • String: 基本的な文字列、数値、バイナリデータ
  • Hash: オブジェクトの表現に適したフィールド-値マップ
  • List: 順序付きリスト、キューやスタックとして利用
  • Set: 重複のない文字列集合
  • Sorted Set: スコア付き順序集合
  • Stream: ログライクなデータ構造
  • Bitmap: ビット操作対応
  • HyperLogLog: 近似カーディナリティ計算

パフォーマンス特性

  • インメモリ処理による超高速アクセス
  • 単一スレッドアーキテクチャによる一貫性保証
  • パイプライニングによる大量操作の効率化
  • 非同期レプリケーション

拡張機能

  • 永続化(RDB、AOF)
  • Master-Slave レプリケーション
  • Redis Cluster による自動シャーディング
  • Pub/Sub メッセージング
  • Lua スクリプト実行
  • Redis Modules による機能拡張

インストール

Ubuntu/Debian

# 公式リポジトリからインストール
sudo apt update
sudo apt install redis-server

# または最新版のインストール
curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
sudo apt-get update
sudo apt-get install redis

CentOS/RHEL

# EPEL リポジトリの有効化
sudo dnf install epel-release
sudo dnf install redis

# または公式リポジトリから
sudo dnf install https://packages.redis.io/rpm/el9/x86_64/redis-8.0-1.el9.x86_64.rpm

Docker

# Redis 8.0の起動
docker run --name redis-cache \
  -p 6379:6379 \
  -d redis:8.0-alpine

# 設定ファイルとデータ永続化
docker run --name redis-cache \
  -v redis_data:/data \
  -v /path/to/redis.conf:/usr/local/etc/redis/redis.conf \
  -p 6379:6379 \
  -d redis:8.0-alpine redis-server /usr/local/etc/redis/redis.conf

ソースからのビルド

# 必要な依存関係
sudo apt-get install build-essential tcl

# Redis のダウンロードとビルド
wget https://download.redis.io/redis-stable.tar.gz
tar xzf redis-stable.tar.gz
cd redis-stable
make
make test
sudo make install

基本設定

redis.conf

# ネットワーク設定
bind 127.0.0.1 ::1
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300

# 一般設定
daemonize yes
pidfile /var/run/redis/redis-server.pid
loglevel notice
logfile /var/log/redis/redis-server.log

# スナップショット設定
dir /var/lib/redis
dbfilename dump.rdb
save 60 1000
save 300 100
save 900 1

# AOF設定
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# メモリ設定
maxmemory 256mb
maxmemory-policy allkeys-lru

# セキュリティ
requirepass your_password_here
# rename-command FLUSHDB ""
# rename-command FLUSHALL ""

# レプリケーション設定
# replicaof <masterip> <masterport>
# masterauth <master-password>

# クライアント設定
maxclients 10000

基本操作

文字列操作

# 基本的なSet/Get
SET user:1000:name "John Doe"
GET user:1000:name
MSET user:1001:name "Jane Doe" user:1001:email "[email protected]"
MGET user:1001:name user:1001:email

# 数値操作
SET counter 10
INCR counter
INCRBY counter 5
DECR counter
DECRBY counter 2

# 期限付きキー
SETEX session:abc123 3600 "user_data"
SET temp_key "value" EX 300
TTL session:abc123
EXPIRE temp_key 600

ハッシュ操作

# ハッシュフィールドの設定
HSET user:1000 name "John Doe" email "[email protected]" age 30
HGET user:1000 name
HMGET user:1000 name email
HGETALL user:1000

# ハッシュ操作
HINCRBY user:1000 age 1
HEXISTS user:1000 email
HDEL user:1000 age
HKEYS user:1000
HVALS user:1000

リスト操作

# リストへの追加
LPUSH tasks "task1" "task2" "task3"
RPUSH queue "item1" "item2"

# リストからの取得
LPOP tasks
RPOP queue
LRANGE tasks 0 -1
LLEN tasks

# ブロッキング操作
BLPOP tasks 30
BRPOP queue 30

# リスト間の移動
RPOPLPUSH source destination

セット操作

# セットへの追加
SADD tags "redis" "cache" "database"
SMEMBERS tags
SISMEMBER tags "redis"

# セット演算
SADD set1 "a" "b" "c"
SADD set2 "b" "c" "d"
SINTER set1 set2
SUNION set1 set2
SDIFF set1 set2

# ランダム要素取得
SRANDMEMBER tags 2
SPOP tags

ソートセット操作

# スコア付きでメンバー追加
ZADD leaderboard 100 "player1" 200 "player2" 150 "player3"
ZRANGE leaderboard 0 -1 WITHSCORES
ZREVRANGE leaderboard 0 2 WITHSCORES

# スコア操作
ZINCRBY leaderboard 50 "player1"
ZSCORE leaderboard "player1"
ZRANK leaderboard "player1"

# 範囲クエリ
ZRANGEBYSCORE leaderboard 100 200
ZCOUNT leaderboard 100 200
ZREMRANGEBYSCORE leaderboard 0 99

高度な機能

Pub/Sub メッセージング

# パブリッシャー
PUBLISH news:tech "Redis 8.0 released!"
PUBLISH news:sports "World Cup final tonight"

# サブスクライバー
SUBSCRIBE news:tech news:sports
PSUBSCRIBE news:*

# チャンネル情報
PUBSUB CHANNELS
PUBSUB NUMSUB news:tech
PUBSUB NUMPAT

Redis Streams

# ストリームへのエントリ追加
XADD events * user "john" action "login" timestamp "2024-01-15T10:00:00Z"
XADD events * user "jane" action "logout" timestamp "2024-01-15T10:05:00Z"

# ストリーム読み取り
XRANGE events - +
XREAD COUNT 10 STREAMS events 0

# コンシューマーグループ
XGROUP CREATE events mygroup 0
XREADGROUP GROUP mygroup consumer1 COUNT 1 STREAMS events >
XACK events mygroup 1642234567890-0

# ストリーム情報
XINFO STREAM events
XLEN events

Lua スクリプト

-- アトミックなインクリメント(Lua スクリプト)
local current = redis.call('GET', KEYS[1])
if current == false then
    current = 0
else
    current = tonumber(current)
end

current = current + tonumber(ARGV[1])
redis.call('SET', KEYS[1], current)
redis.call('EXPIRE', KEYS[1], ARGV[2])
return current
# スクリプトの実行
EVAL "local current = redis.call('GET', KEYS[1]); if current == false then current = 0 else current = tonumber(current) end; current = current + tonumber(ARGV[1]); redis.call('SET', KEYS[1], current); redis.call('EXPIRE', KEYS[1], ARGV[2]); return current" 1 counter 10 3600

# スクリプトの登録と実行
SCRIPT LOAD "script_content"
EVALSHA sha1_hash 1 counter 5 1800

クラスタリング

Redis Cluster設定

# 各ノードの設定 (redis.conf)
port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

# クラスタ作成
redis-cli --cluster create \
  127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
  127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
  --cluster-replicas 1

# ノード追加
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000

# スロット再分散
redis-cli --cluster reshard 127.0.0.1:7000

Redis Cluster操作

# クラスタ情報
CLUSTER INFO
CLUSTER NODES
CLUSTER SLOTS

# キーのスロット確認
CLUSTER KEYSLOT mykey

# ノード管理
CLUSTER MEET 127.0.0.1 7006
CLUSTER FORGET node_id
CLUSTER REPLICATE master_node_id

# 手動フェイルオーバー
CLUSTER FAILOVER

レプリケーション

Master-Slave設定

# Master設定 (redis.conf)
bind 0.0.0.0
port 6379
requirepass master_password

# Slave設定 (redis.conf)
replicaof master_ip 6379
masterauth master_password
replica-read-only yes
replica-serve-stale-data yes

レプリケーション操作

# レプリケーション情報
INFO replication

# スレーブの昇格
SLAVEOF NO ONE

# レプリケーション同期
PSYNC replication_id offset

パフォーマンス最適化

メモリ最適化

# メモリ使用量確認
INFO memory
MEMORY USAGE key_name

# メモリ統計
MEMORY STATS

# ガベージコレクション強制実行
DEBUG OBJECT key_name

パフォーマンス監視

# 操作ごとの統計
INFO stats
INFO commandstats

# スローログ確認
SLOWLOG GET 10
SLOWLOG LEN
SLOWLOG RESET

# リアルタイム監視
MONITOR

# レイテンシ監視
LATENCY LATEST
LATENCY HISTORY command

パイプライニング

import redis

r = redis.Redis(host='localhost', port=6379, db=0)

# パイプライニングの使用
pipe = r.pipeline()
pipe.set('key1', 'value1')
pipe.set('key2', 'value2')
pipe.get('key1')
pipe.get('key2')
results = pipe.execute()

セキュリティ

認証設定

# パスワード認証
requirepass your_strong_password

# ACL (Redis 6.0+)
# ユーザー作成
ACL SETUSER alice on >alice_password ~* &* +@all

# 権限確認
ACL LIST
ACL WHOAMI
ACL CAT

ネットワークセキュリティ

# バインドアドレス制限
bind 127.0.0.1 192.168.1.100

# protected mode
protected-mode yes

# 危険なコマンドの無効化
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command EVAL ""
rename-command DEBUG ""

監視とメンテナンス

基本監視

# サーバー情報
INFO server
INFO clients
INFO memory
INFO persistence
INFO stats

# 接続中のクライアント
CLIENT LIST
CLIENT INFO

# キーの分析
SCAN 0 MATCH pattern* COUNT 1000
TYPE keyname
EXISTS key1 key2 key3

データベース管理

# データベース選択
SELECT 1

# データベースサイズ
DBSIZE

# キーの一括削除
FLUSHDB
FLUSHALL

# バックグラウンド保存
BGSAVE
BGREWRITEAOF

# 設定の動的変更
CONFIG GET maxmemory
CONFIG SET maxmemory 512mb
CONFIG REWRITE

トラブルシューティング

# ログファイル確認
tail -f /var/log/redis/redis-server.log

# プロセス確認
ps aux | grep redis

# ネットワーク接続確認
netstat -tlnp | grep 6379

# Redis CLI接続テスト
redis-cli ping
redis-cli --latency
redis-cli --stat

実用例

セッション管理

# セッションデータの保存
HSET session:user123 name "John Doe" email "[email protected]" last_activity "2024-01-15T10:00:00Z"
EXPIRE session:user123 1800

# セッション確認
HGETALL session:user123
TTL session:user123

分散ロック

# ロック取得 (NX: 存在しない場合のみ設定, EX: 期限秒数)
SET lock:resource:123 "process_id" NX EX 30

# ロック解放 (Luaスクリプトでアトミックに)
EVAL "if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) else return 0 end" 1 lock:resource:123 process_id

カウンター・レート制限

# APIレート制限 (sliding window)
EVAL "local key = KEYS[1]; local window = tonumber(ARGV[1]); local limit = tonumber(ARGV[2]); local current = redis.call('INCR', key); if current == 1 then redis.call('EXPIRE', key, window) end; return current <= limit" 1 rate:api:user123 60 100

Redisは、その柔軟性と高性能により、キャッシング、セッション管理、リアルタイム分析、メッセージキューなど、様々な用途で活用されています。豊富なデータ構造とアトミック操作により、複雑なアプリケーション要件にも対応できます。