Redisのユースケース:キャッシュ、キュー、レート制限

Backend2026-10-13TryQuickToolBox

Redisをスタックに追加したものの、単純なキーバリューストアとしてしか使っていませんか?Redisは強力なデータ構造とコマンドを提供し、キャッシュ、キューイング、レート制限をエレガントに解決できます。このガイドでは、これらのパターンを効果的に実装する方法を紹介します。

なぜこれらのユースケースにRedisなのか?

Redisはその速度と汎用性で知られるインメモリデータストアです。文字列、ハッシュ、リスト、セット、ソート済みセットなどをサポートしています。アトミック操作と組み込みの有効期限により、キャッシュ、キュー、レート制限に最適です。さらに、どの言語とも簡単に統合できます。

Redisによるキャッシュ

キャッシュは最も一般的なRedisのユースケースです。頻繁にアクセスされるデータをRedisに保存することで、データベースの負荷を軽減し、応答を高速化します。

基本的なキャッシュアサイドパターン

キャッシュアサイドパターンでは、アプリケーションはまずRedisをチェックします。データがなければ(キャッシュミス)、データベースから取得し、次回のためにRedisに保存します。

import redis
import json

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

def get_user(user_id):
    cache_key = f'user:{user_id}'
    cached = r.get(cache_key)
    if cached:
        return json.loads(cached)
    user = fetch_user_from_db(user_id)  # your DB call
    r.setex(cache_key, 3600, json.dumps(user))  # cache for 1 hour
    return user

ベストプラクティス:

高度なキャッシュパターン

高トラフィックのアプリケーションでは、以下のパターンを検討してください:

Redisによるキュー

Redisのリストとストリームは、シンプルなメッセージキューの構築に最適です。基本的なジョブキューにはリストを、より複雑なイベント処理にはストリームを使用します。

リストを使ったシンプルなジョブキュー

ジョブを追加するには LPUSH を、処理するには BRPOP を使用します。BRPOP はジョブが利用可能になるまでブロックするため、ワーカーにとって効率的です。

# Producer
r.lpush('jobs', json.dumps({'task': 'send_email', 'to': 'user@example.com'}))

# Consumer (worker)
while True:
    _, job_data = r.brpop('jobs', timeout=30)
    job = json.loads(job_data)
    process_job(job)

ベストプラクティス:

イベントソーシングのためのRedis Streams

Redis Streams(Redis 5.0で導入)は、コンシューマグループ、確認応答、リプレイを備えたより堅牢なキューを提供します。イベントを追加するには XADD を、消費するには XREADGROUP を使用します。

# Add event
r.xadd('events', {'type': 'order_placed', 'order_id': '123'})

# Consumer group
r.xgroup_create('events', 'order_processors', id='0', mkstream=True)
while True:
    events = r.xreadgroup('order_processors', 'worker1', {'events': '>'}, count=10, block=5000)
    for event in events:
        process_event(event)
        r.xack('events', 'order_processors', event.id)

Redisによるレート制限

レート制限はAPIを悪用から保護し、公平な使用を保証します。Redisのアトミック操作はリクエストのカウントに最適です。

固定ウィンドウレート制限

各ユーザーのカウンターをインクリメントし、有効期限を設定します。カウントが制限を超えた場合、リクエストをブロックします。

def is_allowed(user_id, limit=100, window=60):
    key = f'rate_limit:{user_id}'
    current = r.incr(key)
    if current == 1:
        r.expire(key, window)
    return current