Redis Sentinelのインストールと設定:本番環境でのRedis高可用性構成

Database tutorial - IT technology blog
Database tutorial - IT technology blog

深夜2時に起きたこと

3年ほど前、深夜2時にアラートが飛んできた。ECシステムのカート機能とセッションが全て落ちていた。原因はOOM killerによるRedisマスターの死亡で、自動復旧の仕組みが何もなかった。開発チームがSSHで入り、手動でレプリカをマスターに昇格させ、アプリの設定を更新してサービスを再起動するまで、約40分のダウンタイムが発生した。

その障害をきっかけに、Redis Sentinelを本格的に調べ始めた。この記事はドキュメントのコピペではなく、実際の運用経験をもとに書いたものだ。

なぜスタンドアロンRedisは本番に不十分なのか

Redisレプリケーション(マスター・レプリカ構成)は読み取りのスケールアウトとバックアップの問題を解決できるが、フェイルオーバーは自動で行われない。マスターが落ちると:

  • レプリカはマスターのダウンを検知するが、自動で昇格しない
  • アプリケーションは古いIPへの接続を続け、大量エラーが発生する
  • 手動対応が必要:レプリカの昇格、接続文字列の更新

比較すると、MongoDBはレプリカセットでプライマリを自動選出し、MySQL 8はGroup Replicationを持ち、PostgreSQLはPatroniやRepmgrを使う。Redisにも同様の仕組みが必要で、Sentinelがその答えだ。

Redis Clusterも選択肢だが、データシャーディングが必要で構成がかなり複雑になる。多くのシステム(セッション、キャッシュ、pub/sub)では、Sentinelで十分であり、障害時のデバッグもはるかに簡単だ

Redis Sentinelの仕組み

SentinelはRedisサーバーとは別の独立したプロセスで、Redisの隣で動作する。通常は監視するだけで何も干渉しない。複数のSentinelを同時に起動すると、分散した意思決定によるフェイルオーバーのためのクォーラムが形成される。

マスター障害時の流れ:

  1. 各Sentinelが1秒ごとにマスターにpingを送り続ける
  2. 1つのSentinelが応答を受け取れなくなると、マスターをSDOWN(主観的ダウン)としてマークする
  3. そのSentinelが他のSentinelに確認し、クォーラム数が同意するとODOWN(客観的ダウン)に昇格する
  4. Sentinel群の中でリーダーが選出される
  5. Sentinelリーダーが最適なレプリカを選び、新マスターに昇格させる
  6. 残りのレプリカの設定を更新し、新マスターからレプリケーションさせる
  7. pub/subチャンネル経由でクライアントに通知する

クォーラムには奇数台のSentinelが必要で、通常は3台。2台でネットワーク分断が発生すると、どちらも単独でクォーラムを達成できずデッドロックとなり、フェイルオーバーが実行できない。

環境準備:3サーバー、1 Sentinelクラスター

実際に本番で使っている構成:

  • 192.168.1.10 — Redisマスター + Sentinel 1
  • 192.168.1.11 — Redisレプリカ1 + Sentinel 2
  • 192.168.1.12 — Redisレプリカ2 + Sentinel 3

3台全てにRedisをインストール(Ubuntu 22.04):

sudo apt update && sudo apt install -y redis-server
sudo systemctl enable redis-server

RedisマスターとレプリカのConfiguration

マスターサーバー192.168.1.10)の/etc/redis/redis.confを編集:

bind 0.0.0.0
protected-mode no
port 6379
requirepass "your_strong_password"
masterauth "your_strong_password"

2台のレプリカサーバー192.168.1.11192.168.1.12)にレプリケーション設定を追加:

bind 0.0.0.0
protected-mode no
port 6379
replicaof 192.168.1.10 6379
requirepass "your_strong_password"
masterauth "your_strong_password"

3台全てでRedisを再起動:

sudo systemctl restart redis-server

# レプリケーションが正常に動作しているか確認
redis-cli -a your_strong_password info replication

マスターの出力にはrole:masterconnected_slaves:2が表示されるはずだ。

Redis SentinelのConfiguration

3台全てのサーバーにSentinel設定ファイルを作成する。重要な注意点:Sentinelはフェイルオーバー時にこのファイルに自動書き込みするため、プロセスにファイルへの書き込み権限が必要だ:

sudo nano /etc/redis/sentinel.conf

設定ファイルの内容は3台とも同じで、sentinel announce-ipのみ各サーバーのIPに変更する:

port 26379
daemonize yes
logfile /var/log/redis/sentinel.log
pidfile /var/run/redis/redis-sentinel.pid

# クラスター名はプロジェクト名にすると分かりやすい
sentinel monitor mymaster 192.168.1.10 6379 2
sentinel auth-pass mymaster your_strong_password

# 何ms応答がなければダウンとみなすか
sentinel down-after-milliseconds mymaster 5000

# フェイルオーバー後に同時に再同期するレプリカ数(1推奨)
sentinel parallel-syncs mymaster 1

# フェイルオーバーのタイムアウト(ms)
sentinel failover-timeout mymaster 10000

# このサーバーの実際のIPを宣言 — NAT/Docker環境では必須
sentinel announce-ip 192.168.1.10
sentinel announce-port 26379

Sentinelを起動:

sudo redis-sentinel /etc/redis/sentinel.conf

# またはsystemdを使用(本番環境推奨)
sudo nano /etc/systemd/system/redis-sentinel.service
[Unit]
Description=Redis Sentinel
After=network.target

[Service]
Type=forking
ExecStart=/usr/bin/redis-sentinel /etc/redis/sentinel.conf
PIDFile=/var/run/redis/redis-sentinel.pid
Restart=always

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now redis-sentinel

Sentinelの動作確認

# Sentinelに接続
redis-cli -p 26379

# クラスター情報を確認
127.0.0.1:26379> SENTINEL masters
127.0.0.1:26379> SENTINEL replicas mymaster
127.0.0.1:26379> SENTINEL sentinels mymaster

# 現在のマスターアドレスを取得(アプリケーションはこのコマンドを使う)
127.0.0.1:26379> SENTINEL get-master-addr-by-name mymaster

実際のフェイルオーバーテスト

セットアップ完了後、必ずこの手順を実施する。フェイルオーバーを一度もテストせずに本番投入することは絶対にしない:

# マスターサーバーでRedisを停止
sudo systemctl stop redis-server

# 別のサーバーでSentinelのログを監視
tail -f /var/log/redis/sentinel.log

# 約10〜15秒後、新しいマスターを確認
redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster

正常に動作していれば、Sentinelのログに選出と昇格のプロセス全体が記録される。新しいマスターは、その時点でレプリケーションオフセットが高い方に応じて192.168.1.11または192.168.1.12になる。

Sentinel経由でアプリケーションを接続する

ここは多くの人が誤解するポイントだ。アプリケーションはRedisマスターに直接接続しない。クライアントがSentinelに「現在のマスターはどこか?」と問い合わせてから接続する。フェイルオーバーが発生すると、クライアントが自動的に新しいマスターを検出するため、アプリケーションの再起動は不要だ。

redis-pyを使ったPythonの例:

from redis.sentinel import Sentinel

sentinel = Sentinel(
    [
        ('192.168.1.10', 26379),
        ('192.168.1.11', 26379),
        ('192.168.1.12', 26379),
    ],
    socket_timeout=0.5,
    password='your_strong_password'
)

# マスター接続を取得(書き込み用)
master = sentinel.master_for('mymaster', socket_timeout=0.5)

# レプリカ接続を取得(読み取り用)
replica = sentinel.slave_for('mymaster', socket_timeout=0.5)

master.set('key', 'value')
print(replica.get('key'))

ioredisを使ったNode.jsの例:

const Redis = require('ioredis');

const redis = new Redis({
  sentinels: [
    { host: '192.168.1.10', port: 26379 },
    { host: '192.168.1.11', port: 26379 },
    { host: '192.168.1.12', port: 26379 },
  ],
  name: 'mymaster',
  password: 'your_strong_password',
  sentinelPassword: 'your_strong_password',
});

実際に遭遇したトラブル

Sentinelを運用する中で経験した実際の落とし穴:

  • masterauthの設定忘れ:フェイルオーバー時、新しいマスターに昇格したレプリカに他のレプリカが認証できずレプリケーションが止まる。よく見られる症状:レプリケーションラグの急増、ノード間のデータ乖離。全ノードでrequirepassmasterauthを必ず設定すること。
  • SentinelのIPアナウンス未設定:NATやDocker環境では、Sentinelが誤った内部IPを自己報告するため、フェイルオーバー後にクライアントが接続できなくなる。クライアントが到達できる実際のIPでsentinel announce-ipを必ず設定すること。
  • sentinel.confのパーミッション問題:Sentinelはフェイルオーバー時に設定ファイルへの書き込みが必要だ。ファイルがrootの所有でSentinelがredisユーザーとして動作している場合、フェイルオーバーがサイレントに失敗する。明確なエラーが出ず、タイムアウト後に自己回復するだけだ。
  • down-after-millisecondsの設定値が低すぎる:クラウド環境では、ネットワークレイテンシが500ms〜1sにスパイクすることがある。1000msの設定値は誤検知フェイルオーバーを引き起こす可能性がある。本番環境では5000msに設定することが多い。

本番環境でのSentinel監視

redis_exporter経由でPrometheusと連携できる。Sentinelモードに対応済みだ。Prometheusスタックがまだない場合は、定期実行のbashスクリプトで十分対応できる:

#!/bin/bash
MASTER=$(redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster | head -1)
echo "現在のマスター: $MASTER"

# マスターが取得できない場合はアラート
if [ -z "$MASTER" ]; then
  echo "アラート: Redisマスターを特定できません!" | mail -s "Redis Sentinel Alert" [email protected]
fi

Redis Sentinelは全ての問題を解決するわけではない。大規模データで本格的なシャーディングが必要になればRedis Clusterが次のステップだ。しかし、一般的なユースケースの90%(セッション、キャッシュ、キュー)では、Sentinelは十分に強力で、深夜の障害時でもデバッグしやすく、そして何より重要なのは、深夜2時に電話で叩き起こされることがなくなることだ。

Share: