Docker Composeで構築するRedis Sentinelクラスタ:高可用性(HA)構成と自動フェイルオーバー

Docker tutorial - IT technology blog
Docker tutorial - IT technology blog

想定される障害リスク:単一のRedisサーバーが突如ダウンした時

セール開催のピークタイムを迎え、システムは10,000件の同時アクセスを処理しているとします。5ms未満の高速レスポンスを維持するため、ユーザーのログインセッションやショッピングカートのデータはすべてRedisのメモリ上に保持されています。しかし突然、Redisサーバーがメモリ枯渇を起こすか、OSのカーネルによってプロセスが強制終了(OOM Kill)されてしまいました。瞬く間にアプリケーションは500エラーを連発し、ユーザーは決済ができなくなります。

これは単一障害点(Single Point of Failure – SPOF)が引き起こす典型的なシナリオです。Redisを単一ノードだけで運用している場合、エンジニアがアラートを受け取り、サーバーにSSHでログインしてサービスを手動再起動するまで待つ必要があります。その復旧作業には通常15分から30分を要します。この課題を根本から解決するのが、自動フェイルオーバーを備えた高可用性(High Availability – HA)アーキテクチャの導入です。

Redis Sentinelの動作メカニズム

Redis Sentinelは独立した監視・判定システムとして機能し、ユーザーデータの保存処理には直接関与しません。この構成は主に以下の3つのコンポーネントから成り立っています:

  • Redis Master:すべての書き込み(Write)操作を受け付け、読み込み(Read)も処理します。クラスタ内で同時に稼働できるMasterは常に1台のみです。
  • Redis Replica (Slave):Masterからリアルタイムにデータを継続同期し、読み込みクエリの負荷分散を担います。
  • Redis Sentinel:定期的なpingパケットを通じてMasterとReplicaのヘルス状態を常時監視するプロセス群です。

Masterが規定の時間(通常は5秒)を超えて応答を停止すると、あるSentinelがそれを個別検出によるダウン(Subjectively Down – sdown)と判定します。このSentinelは直ちに他のSentinelへ確認シグナルを送信します。定足数(Quorum)に達する合意票が集まると、クラスタ全体としての障害確定(Objectively Down – odown)と認定されます。

障害が確定すると、Sentinel群の中からフェイルオーバーを実行するリーダーが選出されます。リーダーはレプリケーション遅延が最も少ないReplicaを選定し、新たなMasterへと昇格させます。この一連のプロセスはわずか5〜7秒程度で完了し、手動でのコマンド操作は一切不要です。

注意:本番環境では最低3台のSentinelノードが必要です。奇数ノード構成にすることで過半数の合意(Quorum = 2)を確実に得られるようになり、ネットワーク分断時におけるスプリットブレイン(Split-brain)現象を防ぎます。

実践:Docker ComposeによるRedis Sentinelクラスタの構築

Dockerでこの構成を構築する際によくある落とし穴が、1つのsentinel.confファイルを3台のコンテナで共有マウントしてしまうことです。起動時、Sentinelは自身の一意なmyidを自動生成し、設定ファイルに直接書き込みます。同じファイルを共有するとIDの競合が発生し、クラスタ全体が正常に動作しなくなります。以下では、3つの独立した設定ファイルを用意する正しい構築手順を解説します。

1. ディレクトリ構成の準備

プロジェクト用ディレクトリを作成し、各Sentinel専用の設定ファイルを用意します:

mkdir -p redis-sentinel-ha/sentinel && cd redis-sentinel-ha
touch sentinel/sentinel-1.conf sentinel/sentinel-2.conf sentinel/sentinel-3.conf

2. sentinel-1.confの設定

sentinel/sentinel-1.confに以下の内容を記述します(sentinel-2.confおよびsentinel-3.confにも同様に記述してください):

port 26379
dir /tmp
sentinel monitor mymaster redis-master 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 10000
sentinel parallel-syncs mymaster 1

各設定パラメータの技術的な意味:

  • sentinel monitor mymaster redis-master 6379 2:監視グループ名をmymasterに設定し、ホスト名redis-masterのポート6379を指定。フェイルオーバーをトリガーするために最低2台のSentinelによる合意を要求します。
  • down-after-milliseconds mymaster 5000:5,000ms(5秒間)pingへの応答がない場合、Masterがダウンしたとみなします。
  • failover-timeout mymaster 10000:フェイルオーバー処理全体のタイムアウトを10秒に設定します。この時間を超過した場合、別のSentinelが処理を再試行します。
  • parallel-syncs mymaster 1:新しいMasterに対して同時にデータ再同期を行えるReplicaの数を指定します。ネットワーク帯域の枯渇を防ぐため、1に保ちます。

3. docker-compose.ymlの作成

内部ブリッジネットワークを介して相互通信を行う1台のMaster、1台のReplica、3台のSentinelを定義します:

version: '3.8'

networks:
  redis-net:
    driver: bridge

services:
  redis-master:
    image: redis:7-alpine
    container_name: redis-master
    ports:
      - "6379:6379"
    networks:
      - redis-net

  redis-replica:
    image: redis:7-alpine
    container_name: redis-replica
    ports:
      - "6380:6379"
    command: redis-server --replicaof redis-master 6379
    depends_on:
      - redis-master
    networks:
      - redis-net

  sentinel-1:
    image: redis:7-alpine
    container_name: sentinel-1
    command: redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./sentinel/sentinel-1.conf:/etc/redis/sentinel.conf
    ports:
      - "26379:26379"
    depends_on:
      - redis-master
      - redis-replica
    networks:
      - redis-net

  sentinel-2:
    image: redis:7-alpine
    container_name: sentinel-2
    command: redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./sentinel/sentinel-2.conf:/etc/redis/sentinel.conf
    ports:
      - "26380:26379"
    depends_on:
      - redis-master
      - redis-replica
    networks:
      - redis-net

  sentinel-3:
    image: redis:7-alpine
    container_name: sentinel-3
    command: redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./sentinel/sentinel-3.conf:/etc/redis/sentinel.conf
    ports:
      - "26381:26379"
    depends_on:
      - redis-master
      - redis-replica
    networks:
      - redis-net

4. 起動とクラスタステータスの検証

以下のコマンドを実行してシステム全体を起動します:

docker compose up -d

Sentinel側からMasterが正しく認識されているか状態を確認します:

docker exec -it sentinel-1 redis-cli -p 26379 sentinel master mymaster

出力結果の中にある2つの重要なパラメータに注目してください。num-slavesが1、num-other-sentinelsが2になっていれば、3台のSentinel間で正常にハンドシェイクが完了しています。

5. 自動フェイルオーバーの動作検証

Masterコンテナを停止して擬似的に障害を発生させます:

docker stop redis-master

Sentinelのログからイベントの流れをリアルタイムに監視します:

docker logs -f sentinel-1

ログには以下の主要イベントが時系列順に出力されます:

  • +sdown master mymaster 172.x.x.x 6379:5秒間PONG応答がないため、Sentinel-1がMasterを局所的なダウン状態と判定。
  • +odown master mymaster 172.x.x.x 6379 #quorum 2/2:2票の合意(Quorum)に達し、クラスタ全体としての障害を確定。
  • +try-failover master mymaster...:フェイルオーバープロセスの開始。
  • +switch-master mymaster redis-master 6379 redis-replica 6379:Replicaを昇格させ、新Masterへの切り替えを実行。

現在のredis-replicaのロールを確認します:

docker exec -it redis-replica redis-cli role

1行目にmasterと出力されます。システムが約6秒で自動復旧したことが確認できました。なお、元のredis-masterコンテナをdocker start redis-masterで再起動すると、Sentinelによって自動的にReplicaへ降格され、新Masterからのデータ同期を開始します。

まとめ

Redis Sentinelは、中小規模のシステムにおいて運用コストと信頼性のバランスに優れたソリューションです。単一ノード障害から読み書き処理を保護することが主な目的であれば、複雑なRedis Clusterを導入する必要はありません。設定ファイルを個別に分離し、Docker Composeの内部ネットワークを活用することで、本番導入前のフェイルオーバー検証環境を正確に構築できます。

Share: