📝

Redisと仲良くなってみたよ!!

に公開

概要

・今回案件で初めて触る機会があったのでまとめてみました!
・個人的にふんわりのイメージでしかなく、苦手意識があったので誰かの一助になれば幸いです🫡

1. Redisとは

Redisの概要と誕生の背景

Redis(Remote Dictionary Server)は、オープンソースのインメモリデータストアです。
現在では、Twitter、GitHub、Stack Overflow、Airbnbなど、世界中の多くの企業で採用されている実績のあるデータベースシステムです。

インメモリデータベースの特徴

Redisはインメモリデータベースです。これは、データを主にRAM(メモリ)上に保存することを意味します。

メモリ上にデータを保存することの利点:

  • 極めて高速なデータアクセス(マイクロ秒単位)
  • ディスクI/Oのボトルネックがない
  • リアルタイム処理に最適

注意点:

  • メモリ容量に制限される
  • サーバー再起動時にデータが失われる可能性(ただし永続化機能で対策可能)

他のデータベース(MySQL、PostgreSQL)との違い

特徴 Redis MySQL/PostgreSQL
データ保存場所 メモリ(RAM) ディスク
処理速度 非常に高速(マイクロ秒) 比較的遅い(ミリ秒)
データ構造 Key-Value、List、Set等 テーブル(行と列)
クエリ言語 シンプルなコマンド SQL
主な用途 キャッシュ、セッション管理 永続的なデータ保存
データ容量 メモリ容量に依存 ディスク容量に依存
トランザクション 限定的なサポート 完全なACIDサポート

**Redisは従来のRDBMSを置き換えるものではなく、補完するものです。**多くのシステムでは、MySQLやPostgreSQLと併用されます。

なぜRedisが必要なのか

Webアプリケーションを開発していると、以下のような課題に直面します:

課題1:データベースへの負荷

  • 同じクエリが何度も実行される
  • レスポンスが遅くなる
  • データベースサーバーのCPU使用率が高騰

課題2:セッション管理

  • 複数のWebサーバーでセッションを共有したい
  • ファイルベースのセッション管理では限界がある

課題3:リアルタイム機能

  • ランキングやカウンターをリアルタイムで更新したい
  • データベースでは処理が重い

Redisはこれらの課題を解決します:

  • 高速なキャッシュ機能でデータベース負荷を軽減
  • セッションの一元管理と共有
  • リアルタイムデータの高速処理

実務での採用理由と導入事例

採用理由

  1. パフォーマンス向上

    • データベースクエリの応答時間を数百ミリ秒から数ミリ秒に短縮
    • サーバーリソースの効率的な利用
  2. スケーラビリティ

    • 水平スケーリングが容易
    • レプリケーション機能による可用性向上
  3. 開発効率

    • シンプルなAPI
    • 豊富なクライアントライブラリ
    • 学習コストが低い
  4. 柔軟なデータ構造

    • 用途に応じた最適なデータ構造を選択可能
    • 複雑なロジックをRedis側で処理可能

実際の導入事例

Twitter

  • タイムラインのキャッシュ
  • 数億のキー-バリューペアを管理

GitHub

  • ジョブキューの管理(Resque)
  • レート制限の実装

Stack Overflow

  • ページビューカウンター
  • セッション管理

Airbnb

  • 検索結果のキャッシュ
  • 予約システムの在庫管理

2. Redisの主な特徴

高速性の秘密

メモリベースの仕組み

Redisがこれほど高速な理由は、すべてのデータをメモリ(RAM)上に保持しているためです。

ディスクアクセス vs メモリアクセスの速度比較:

  • ディスク(HDD): 5-10ms
  • ディスク(SSD): 0.1-1ms
  • メモリ(RAM): 0.0001ms(100ナノ秒)

つまり、メモリアクセスはディスクアクセスの1万〜10万倍高速です。

シングルスレッドモデル

Redisはシングルスレッドで動作します。一見すると制約のように思えますが、これがRedisの高速性と信頼性の源です。

シングルスレッドの利点:

  • 競合状態(race condition)が発生しない
  • ロックの必要がない
  • CPUコンテキストスイッチのオーバーヘッドがない
  • コードがシンプルで予測可能

なぜシングルスレッドでも高速?

  • メモリアクセスはCPU処理よりも遥かに高速
  • ネットワークI/Oは非同期で処理
  • 1つのコマンド実行時間が非常に短い(マイクロ秒単位)

ベンチマーク結果

一般的なハードウェアでのRedisのパフォーマンス:

SET操作: 約100,000 ops/sec
GET操作: 約100,000 ops/sec
INCR操作: 約100,000 ops/sec

※ パイプライン処理を使用すると、さらに高速化が可能(数十万〜数百万ops/sec)

データの永続化機能

Redisはインメモリデータベースですが、データを永続化する機能も持っています。

RDB(スナップショット)

仕組み:

  • 定期的にメモリ上のデータセット全体をディスクに保存
  • バイナリ形式で圧縮されたファイル(dump.rdb)

設定例:

save 900 1      # 900秒間に1回以上の変更があれば保存
save 300 10     # 300秒間に10回以上の変更があれば保存
save 60 10000   # 60秒間に10000回以上の変更があれば保存

メリット:

  • ファイルサイズが小さい
  • 復旧が高速
  • パフォーマンスへの影響が少ない

デメリット:

  • 最後のスナップショット以降のデータは失われる可能性
  • データセットが大きい場合、保存に時間がかかる

AOF(Append Only File)

仕組み:

  • すべての書き込みコマンドをログファイルに記録
  • サーバー起動時にログを再実行してデータを復元

同期オプション:

appendfsync always    # 毎回同期(最も安全だが遅い)
appendfsync everysec  # 1秒ごとに同期(推奨)
appendfsync no        # OSに任せる(最も高速だが危険)

メリット:

  • データ損失のリスクが低い
  • ログファイルは人間が読める形式
  • 自動的にファイルの再構築(リライト)を実行

デメリット:

  • ファイルサイズが大きくなりやすい
  • 復旧に時間がかかる
  • パフォーマンスへの影響がある

実務での推奨設定:

  • 重要なデータ:AOF(everysec)
  • キャッシュなど揮発性データ:RDBのみ、または永続化なし
  • 最も安全:RDB + AOF の併用

豊富なデータ構造

Redisは単純なKey-Valueストア以上の機能を提供します。

利用可能なデータ構造

  1. String(文字列)

    • 最も基本的なデータ型
    • バイナリセーフ(画像なども保存可能)
    • 最大512MB
  2. List(リスト)

    • 順序付きの文字列コレクション
    • 両端からの追加・削除が高速
    • キューやスタックとして利用可能
  3. Set(セット)

    • 重複のない文字列コレクション
    • 集合演算(和集合、積集合、差集合)が可能
  4. Hash(ハッシュ)

    • フィールドと値のマッピング
    • オブジェクトを表現するのに最適
  5. Sorted Set(ソート済みセット)

    • スコア付きのセット
    • スコア順にソートされる
    • ランキングやタイムライン実装に最適

レプリケーションとクラスタリング

レプリケーション(マスター-レプリカ)

仕組み:

  • マスターノードのデータがレプリカノードに自動的に複製される
  • 読み取り負荷を分散できる
  • 障害時の可用性向上

設定:

# レプリカノードの設定
replicaof 192.168.1.100 6379

Redis Sentinel

  • 自動フェイルオーバー機能
  • マスターの監視と障害検知
  • 自動的に新しいマスターを選出

Redis Cluster

  • データを複数ノードに自動分散
  • 数千のノードまでスケール可能
  • 高可用性と水平スケーリングを実現

シンプルなコマンド体系

Redisのコマンドは直感的で覚えやすいです。

基本コマンドの例:

SET key value        # 設定
GET key              # 取得
DEL key              # 削除
EXISTS key           # 存在確認
EXPIRE key seconds   # 有効期限設定
TTL key              # 残り時間確認
KEYS pattern         # パターンマッチ検索

コマンドは動詞+名詞の形式が多く、英語の意味そのままで理解できます。


3. Redisの主な用途

キャッシュとしての利用

最も一般的なRedisの使用方法です。

データベースクエリのキャッシュ

問題:
データベースクエリは時間がかかり、頻繁に実行されると負荷が高くなります。

解決策:
クエリ結果をRedisにキャッシュし、次回以降は高速に取得します。

効果:

  • クエリ応答時間:300ms → 3ms(100倍高速化)
  • データベース負荷の大幅削減

APIレスポンスのキャッシュ

外部APIの呼び出し結果をキャッシュすることで、レスポンス時間を短縮し、API呼び出し回数を削減できます。

実装例:

ユーザーが天気情報を要求
↓
Redisにキャッシュがあるか確認
↓
ある → Redisから返す(1ms)
ない → APIを呼び出してRedisに保存し返す(500ms)

キャッシュ戦略

1. Cache-Aside(Lazy Loading)

  • 最も一般的なパターン
  • データが要求されたときにキャッシュをチェック
  • キャッシュミス時にデータベースから取得してキャッシュに保存

フロー:

1. アプリケーション → Redisにデータを要求
2. キャッシュヒット → データを返す
3. キャッシュミス → DBから取得 → Redisに保存 → データを返す

2. Write-Through

  • データ書き込み時に同時にキャッシュも更新
  • キャッシュとデータベースの一貫性が保たれる

フロー:

1. データ書き込み → DBに保存
2. 同時に → Redisにも保存

3. Write-Behind(Write-Back)

  • まずキャッシュに書き込み
  • 非同期でデータベースに書き込み
  • 書き込みパフォーマンスが向上

セッション管理

Webアプリケーションのセッションストア

従来の課題:

  • ファイルベースのセッション管理は遅い
  • 単一サーバーに依存

Redisによる解決:

  • 高速なセッション読み書き
  • すべてのWebサーバーからアクセス可能
  • 自動的にセッションの有効期限を管理(TTL機能)

複数サーバー間でのセッション共有

シナリオ:
ロードバランサーで複数のWebサーバーに振り分けられる環境

Redisの役割:

ユーザー → ロードバランサー → サーバー1 ┐
                              → サーバー2 ├→ Redis(セッション)
                              → サーバー3 ┘

どのサーバーにリクエストが来ても、Redisから同じセッション情報を取得できます。

リアルタイムランキング

ゲームのスコアボード

要件:

  • リアルタイムでスコアを更新
  • 上位N人を高速に取得
  • ユーザーの順位を瞬時に表示

Redisの実装:
Sorted Set(ソート済みセット)を使用することで、これらの要件を簡単に実現できます。

処理速度:

  • スコア更新:O(log(N))
  • 上位取得:O(log(N)+M)
  • 順位取得:O(log(N))

数百万のエントリーがあっても、ミリ秒単位で処理できます。

トレンド記事ランキング

使用例:

  • ページビュー数順
  • いいね数順
  • コメント数順

時間帯別やカテゴリ別のランキングも容易に実装できます。

メッセージキュー/Pub/Sub

非同期処理のキュー

用途:

  • メール送信
  • 画像処理
  • レポート生成
  • その他の時間のかかる処理

Redisの役割:

Webアプリ → Redisキュー → ワーカープロセス → 実際の処理

利点:

  • ユーザーレスポンスが高速
  • 処理の分散が可能
  • 障害時の再実行が容易

リアルタイム通知

Pub/Sub機能:

  • Publisher(発行者)がメッセージを送信
  • Subscriber(購読者)がメッセージを受信
  • 複数の購読者に同時配信可能

実装例:

  • チャットアプリケーション
  • リアルタイムダッシュボード
  • 通知システム

分散ロック

排他制御が必要な処理

問題:
複数のサーバーで同時に同じ処理を実行してはいけない場合

例:

  • 定期的なバッチ処理
  • チケット予約システム
  • 在庫管理

Redisによる実装:

SET lock_key unique_value NX PX 30000
  • NX:キーが存在しない場合のみ設定
  • PX:ミリ秒単位の有効期限

この仕組みにより、複数のプロセス間で排他制御を実現できます。

レート制限(Rate Limiting)

API呼び出し制限

要件:

  • 1ユーザーあたり1時間に100回までAPIを呼び出し可能
  • 制限を超えた場合はエラーを返す

実装方法:

  1. 固定ウィンドウ方式

    • シンプルで実装が容易
    • 時間境界での集中アクセスに弱い
  2. スライディングウィンドウ方式

    • より正確な制限
    • Sorted Setを使用して実装

ログイン試行回数制限

セキュリティ対策:

  • ブルートフォース攻撃の防止
  • 10分間に5回失敗したら一時的にロック

Redisでの実装:

# 試行回数をインクリメント
INCR login_attempts:user123

# 初回の場合は有効期限を設定
EXPIRE login_attempts:user123 600  # 10分

その他の実務での使用例

カウンター(ページビュー、いいね数)

特徴:

  • アトミックな増減操作(INCR/DECR)
  • 競合状態が発生しない
  • 非常に高速

実装例:

# ページビューをカウント
INCR pageviews:article:123

# いいね数をカウント
INCR likes:post:456

ジオロケーション

Geo機能:

  • 位置情報(緯度・経度)を保存
  • 特定の範囲内の地点を検索
  • 2点間の距離を計算

使用例:

  • 近くのレストラン検索
  • 配達エリア判定
  • 位置情報ゲーム

フルテキスト検索(RediSearch)

RediSearchモジュール:

  • 高速な全文検索
  • 多言語サポート
  • オートコンプリート機能

用途:

  • サイト内検索
  • ログ検索
  • ドキュメント検索

まとめ

Redisは、高速性、柔軟性、シンプルさを兼ね備えたインメモリデータストアです。キャッシュ、セッション管理、ランキング、キューなど、多様な用途で活用できます。

次の記事では、実際にRedisを操作しながら、具体的な使い方を学んでいきます。基本的なコマンドからデータ構造の使い分け、実践的な実装パターンまで、実務で必要な知識を身につけていきましょう。

更新(2025/12/3追記)

次の記事を作成しました!この記事の続きになります。以下よりぜひ読んで頂けますと幸いです🙇‍♀️
https://zenn.dev/osakayakyu/articles/9da61f0dc688b7

Discussion