mcpField
R
redis-best-practices

redis-best-practices

github.com/mindrallyデータ・データベース2872.2k 回インストール3 週間前に更新
リポジトリ

redis-best-practices について

redis-best-practices は、Redis を使うアプリケーションの開発・運用向けガイドです。データ構造、キャッシュ、信頼性、セキュリティ、性能をコマンド例とともに扱います。

主な機能

  1. 01Redis データ構造の選択指針
  2. 02キー命名と有効期限の方針
  3. 03キャッシュと無効化のパターン
  4. 04トランザクションと原子操作
  5. 05高可用性、永続化、セキュリティ
  6. 06監視と性能改善の実践

活用シーン

  1. 01キューやランキング向け構造の選定
  2. 02キャッシュ TTL と無効化の設計
  3. 03Redis のレプリケーションと永続化の計画
  4. 04Redis のメモリと接続設定の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mindrally/skills --skill redis-best-practices

インストール後、Claude Code で/redis-best-practicesを入力して読み込まれたか確認します。

詳細

Redis のベストプラクティス

基本原則

  • キャッシュ、セッションストレージ、リアルタイム分析、メッセージキューには Redis を使用します
  • 用途に適したデータ構造を選択します
  • 適切なキー命名規則と有効期限ポリシーを実装します
  • 高可用性と永続化の要件を考慮して設計します
  • メモリ使用量を監視し、パフォーマンスを最適化します

キー命名規則

  • 名前空間の区切りにはコロンを使用します
  • キー名にはオブジェクトの種類と識別子を含めます
  • キーは短く、内容がわかる名前にします
  • アプリケーション全体で一貫した命名パターンを使用します
# Good key naming examples
user:1234:profile
user:1234:sessions
order:5678:items
cache:api:products:list
queue:email:pending
session:abc123def456
rate_limit:api:user:1234

データ構造

文字列
  • シンプルなキーと値の保存、カウンター、キャッシュに使用します
  • 一括操作には MGET/MSET の使用を検討します
# Simple caching
SET cache:user:1234 '{"name":"John","email":"[email protected]"}' EX 3600

# Counters
INCR stats:pageviews:homepage
INCRBY stats:downloads:file123 5

# Atomic operations
SETNX lock:resource:456 "owner:abc" EX 30
ハッシュ
  • 複数のフィールドを持つオブジェクトに使用します
  • 複数の文字列キーを使うよりメモリ効率に優れています
  • 部分的な更新に対応しています
# Store user profile
HSET user:1234 name "John Doe" email "[email protected]" created_at "2024-01-15"

# Get specific fields
HGET user:1234 email
HMGET user:1234 name email

# Increment numeric fields
HINCRBY user:1234 login_count 1

# Get all fields
HGETALL user:1234
リスト
  • キュー、最近のアイテム、アクティビティフィードに使用します
  • キューのコンシューマーにはブロッキング操作の使用を検討します
# Message queue
LPUSH queue:emails '{"to":"[email protected]","subject":"Welcome"}'
RPOP queue:emails

# Blocking pop for workers
BRPOP queue:emails 30

# Recent activity (keep last 100)
LPUSH user:1234:activity "viewed product 567"
LTRIM user:1234:activity 0 99

# Get recent items
LRANGE user:1234:activity 0 9
セット
  • 重複のないコレクション、タグ、関連付けに使用します
  • セット演算(和集合、積集合、差集合)に対応しています
# User tags/interests
SADD user:1234:interests "technology" "music" "travel"

# Check membership
SISMEMBER user:1234:interests "music"

# Find common interests
SINTER user:1234:interests user:5678:interests

# Online users tracking
SADD online:users "user:1234"
SREM online:users "user:1234"
SMEMBERS online:users
ソート済みセット
  • リーダーボード、優先度キュー、時系列データに使用します
  • 要素はスコア順に並べ替えられます
# Leaderboard
ZADD leaderboard:game1 1500 "player:123" 2000 "player:456" 1800 "player:789"

# Get top 10
ZREVRANGE leaderboard:game1 0 9 WITHSCORES

# Get player rank
ZREVRANK leaderboard:game1 "player:123"

# Time-based data (score = timestamp)
ZADD events:user:1234 1705329600 "login" 1705330000 "purchase"

# Get events in time range
ZRANGEBYSCORE events:user:1234 1705329600 1705333200
ストリーム
  • イベントストリーミングとログデータに使用します
  • 分散処理用のコンシューマーグループに対応しています
# Add events to stream
XADD events:orders * customer_id 1234 product_id 567 amount 99.99

# Read from stream
XREAD COUNT 10 STREAMS events:orders 0

# Consumer groups
XGROUP CREATE events:orders order-processors $ MKSTREAM
XREADGROUP GROUP order-processors worker1 COUNT 10 STREAMS events:orders >

# Acknowledge processed messages
XACK events:orders order-processors 1234567890-0

キャッシュパターン

キャッシュ・アサイドパターン
# Pseudo-code for cache-aside
def get_user(user_id):
    # Try cache first
    cached = redis.get(f"cache:user:{user_id}")
    if cached:
        return json.loads(cached)

    # Cache miss - fetch from database
    user = database.get_user(user_id)

    # Store in cache with expiration
    redis.setex(f"cache:user:{user_id}", 3600, json.dumps(user))

    return user
ライトスルーパターン
def update_user(user_id, data):
    # Update database
    database.update_user(user_id, data)

    # Update cache
    redis.setex(f"cache:user:{user_id}", 3600, json.dumps(data))
キャッシュの無効化
# Delete specific cache
DEL cache:user:1234

# Delete by pattern (use with caution in production)
# Use SCAN instead of KEYS for large datasets
SCAN 0 MATCH cache:user:* COUNT 100

# Tag-based invalidation using sets
SADD cache:tags:user:1234 "cache:user:1234:profile" "cache:user:1234:orders"
# Invalidate all related caches
SMEMBERS cache:tags:user:1234
# Then delete each key

有効期限とメモリ管理

TTL のベストプラクティス
  • キャッシュキーには必ず TTL を設定します
  • 大量アクセスの集中を防ぐため、ジッターを使用します
  • セッションデータにはスライディング有効期限の使用を検討します
# Set with expiration
SET cache:data:123 "value" EX 3600

# Set expiration on existing key
EXPIRE cache:data:123 3600

# Check TTL
TTL cache:data:123

# Persist key (remove expiration)
PERSIST cache:data:123
メモリ管理
# Check memory usage
INFO memory

# Get key memory usage
MEMORY USAGE cache:large:object

# Configure max memory policy
CONFIG SET maxmemory 2gb
CONFIG SET maxmemory-policy allkeys-lru

トランザクションとアトミック性

MULTI/EXEC トランザクション
# Transaction block
MULTI
INCR stats:views
LPUSH recent:views "page:123"
EXEC

# Watch for optimistic locking
WATCH user:1234:balance
balance = GET user:1234:balance
MULTI
SET user:1234:balance (balance - 100)
EXEC
Lua スクリプト
  • 複雑なアトミック操作に使用します
  • スクリプトはアトミックに実行されます
-- Rate limiting script
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local window = tonumber(ARGV[2])

local current = tonumber(redis.call('GET', key) or '0')

if current >= limit then
    return 0
end

redis.call('INCR', key)
if current == 0 then
    redis.call('EXPIRE', key, window)
end

return 1
# Execute Lua script
EVAL "return redis.call('GET', KEYS[1])" 1 mykey

Pub/Sub とメッセージング

# Publisher
PUBLISH channel:notifications '{"type":"alert","message":"New order"}'

# Subscriber
SUBSCRIBE channel:notifications

# Pattern subscription
PSUBSCRIBE channel:*

高可用性

レプリケーション
  • 読み取り負荷の分散にはレプリカを使用します
  • マスターで適切な永続化を設定します
# On replica
REPLICAOF master_host 6379

# Check replication status
INFO replication
Redis Sentinel
  • 自動フェイルオーバーに使用します
  • Sentinel インスタンスを少なくとも 3 つデプロイします
Redis Cluster
  • 水平スケーリングに使用します
  • データはノード間で自動的にシャーディングされます
  • 関連するキーにはハッシュタグを使用します
# Hash tags ensure keys go to same slot
SET {user:1234}:profile "data"
SET {user:1234}:settings "data"

永続化

RDB スナップショット
# Manual snapshot
BGSAVE

# Configure automatic snapshots
CONFIG SET save "900 1 300 10 60 10000"
AOF(追加専用ファイル)
# Enable AOF
CONFIG SET appendonly yes
CONFIG SET appendfsync everysec

# Rewrite AOF
BGREWRITEAOF

セキュリティ

  • 認証を必須にします
  • 接続には TLS を使用します
  • 特定のインターフェースにバインドします
  • 危険なコマンドを無効にします
# Set password
CONFIG SET requirepass "your_strong_password"

# Authenticate
AUTH your_strong_password

# Rename dangerous commands (in redis.conf)
rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command KEYS ""

監視

# Server info
INFO

# Memory stats
INFO memory

# Client connections
CLIENT LIST

# Slow log
SLOWLOG GET 10

# Monitor commands (debug only)
MONITOR

# Key count per database
INFO keyspace

接続管理

  • コネクションプーリングを使用します
  • 適切なタイムアウトを設定します
  • 再接続を適切に処理します
# Python example with connection pool
import redis

pool = redis.ConnectionPool(
    host='localhost',
    port=6379,
    max_connections=50,
    socket_timeout=5,
    socket_connect_timeout=5
)

redis_client = redis.Redis(connection_pool=pool)

パフォーマンスのヒント

  • 一括操作にはパイプラインを使用します
  • 大きなキー(値が 100KB を超えるもの)は避けます
  • 本番環境では KEYS の代わりに SCAN を使用します
  • メモリ使用量を監視し、最適化します
  • 複雑な JSON 操作には RedisJSON の使用を検討します
# Pipeline example (pseudo-code)
pipe = redis.pipeline()
pipe.get("key1")
pipe.get("key2")
pipe.set("key3", "value")
results = pipe.execute()

コメント