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

Backend2026-10-05TryQuickToolBox

Webアプリケーションを構築し、それが traction を得ているとします。しかし、トラフィックが増えるにつれて、データベースクエリの遅延や時折発生するタイムアウトに気づきます。サーバーは負荷に苦しみ、ユーザーはレイテンシについて不満を言います。反復的なタスクをオフロードし、トラフィックスパイクを管理するために、高速なインメモリデータストアが必要です。Redisは多くのバックエンド課題に対する頼りになるソリューションであり、この記事では、キャッシュ、キュー、レート制限という3つの実用的なユースケースを探ります。

なぜRedisなのか?

Redisは、その速度と汎用性で知られるオープンソースのインメモリキーバリューストアです。文字列、ハッシュ、リスト、セット、ソート済みセットなどのデータ構造をサポートし、幅広いタスクに適しています。従来のデータベースとは異なり、RedisはデータをRAMに保持し、サブミリ秒のレイテンシを実現します。また、永続化オプション、レプリケーション、高可用性のためのクラスタリングも提供します。

1. Redisによるキャッシュ

キャッシュは最も一般的なRedisのユースケースです。頻繁にアクセスされるデータをRedisに保存することで、プライマリデータベースの負荷を軽減し、応答時間を短縮できます。たとえば、アプリケーションが人気商品のリストを表示する場合、クエリ結果を数分間キャッシュできます。

キャッシュの実装方法

  1. キャッシュをチェック: データベースにクエリする前に、データがRedisに存在するか確認します。
  2. 見つかった場合(キャッシュヒット): キャッシュされたデータを返します。
  3. 見つからない場合(キャッシュミス): データベースにクエリし、結果を有効期限(TTL)付きでRedisに保存し、データを返します。

以下はredis-pyを使用したPythonの例です:

import redis
import json

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

def get_products():
    cache_key = 'products:popular'
    cached = r.get(cache_key)
    if cached:
        return json.loads(cached)
    # Simulate database query
    products = [{'id': 1, 'name': 'Product A'}, {'id': 2, 'name': 'Product B'}]
    r.setex(cache_key, 300, json.dumps(products))  # Cache for 5 minutes
    return products

ベストプラクティス: 意味のあるキャッシュキーを使用し、適切なTTLを設定し、キャッシュ無効化戦略を検討します。頻繁に変更されるデータには、短いTTLを使用するか、ライトスルーキャッシュを実装します。

2. Redisによるキュー

Redisのリストとストリームは、シンプルなメッセージキューの構築に最適です。これらにより、時間のかかるタスク(メール送信や画像処理など)をリクエスト・レスポンスサイクルから分離し、ユーザーエクスペリエンスとスケーラビリティを向上させることができます。

リストをキューとして使用する

LPUSHを使用してリストにジョブを追加し、BRPOPを使用して反対側からアトミックにジョブをポップできます。これによりFIFOキューが作成されます。

プロデューサー:

r.lpush('email_queue', json.dumps({'to': 'user@example.com', 'subject': 'Welcome'}))

コンシューマー(ワーカープロセス内):

while True:
    _, job = r.brpop('email_queue', timeout=30)
    if job:
        process_email(json.loads(job))

考慮事項: Redisのリストはシンプルですが、確認応答などの高度な機能がありません。より堅牢なニーズには、コンシューマーグループとメッセージ確認応答をサポートするRedis Streamsを検討してください。

3. 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