【実務・中級編】 Redis Sentinel – Redis

Redis Sentinel:その「自動フェイルオーバー」という甘い罠と、真の可用性を掴む設計思想

Redisを運用するエンジニアにとって、Sentinelは「とりあえず導入しておけば安心」というお守りになりがちだ。だが、現場で数多の障害を乗り越えてきた経験から言わせれば、Sentinelをブラックボックスとして扱うのは、時限爆弾を抱えるのと同義だ。

なぜなら、Sentinelは単なる「監視ツール」ではなく、「ネットワーク分断という地獄」と「一貫性」の狭間で踊る、極めて繊細な分散合意システムだからだ。

本稿では、教科書的な説明は最小限に留め、本番環境で「刺される」ポイントを解剖し、堅牢なアーキテクチャを構築するための知見を共有する。

—

1. Sentinelは「分散合意」の戦場である

まず叩き込んでおくべきは、Sentinelのアーキテクチャが「多数決(Quorum)」という民主主義的な合意形成に基づいているという事実だ。

  • Quorum(クォーラム)の意味: 障害を検知したSentinelが「マスターが死んだ」と判断する最小人数。
  • 脳死状態の回避: 全てのSentinelが独立して動くわけではない。彼らはGossipプロトコルで通信し、「本当にマスターはダウンしたのか?」を議論する。

【実務上の鉄則】
Sentinelのノード数は、必ず「奇数(3台以上)」にすること。2台ではネットワークの瞬断が発生した瞬間に、双方のSentinelが「相手が死んだ」と誤解し、共倒れ(スプリット・ブレイン)を引き起こす可能性がある。

—

2. 現場で遭遇する「フェイルオーバーの罠」

Sentinelを導入しても、アプリケーションがダウンするケースは後を絶たない。その原因の多くは、クライアント側の「接続のライフサイクル」にある。

罠:IP固定という信仰

多くのエンジニアは、アプリケーション側のRedis接続先に「特定のマスターIP」をハードコードする。これは致命的だ。フェイルオーバーが起きた瞬間、そのIPはゴミとなり、アプリは接続不能に陥る。

【解決策:Sentinel Awareness】
Redisクライアントライブラリ(`go-redis`, `redis-py`, `Jedis`など)は、Sentinelをサポートしている。これらは起動時にSentinelノード群に問い合わせ、「現在のマスターは誰か?」を動的に解決する。

悪い例:IPを直接指定
r = redis.Redis(host=’10.0.0.1′, port=6379)

良い例:Sentinelを認識させる
from redis.sentinel import Sentinel

Sentinelノードを教えるだけで、マスターの追跡はライブラリが勝手にやる
sentinel = Sentinel([(‘sentinel1’, 26379), (‘sentinel2’, 26379)], socket_timeout=0.1)
master = sentinel.master_for(‘mymaster’, socket_timeout=0.1)

ここで取得するmasterは、フェイルオーバー後も自動で新マスターに再接続される
master.set(‘key’, ‘value’)

—

3. パフォーマンスとネットワークの「見えない壁」

Sentinelが誤検知を起こす最大の原因は、Redisの負荷による「一時的な無反応」だ。

  • `down-after-milliseconds` のチューニング:

デフォルト値(通常30秒)は本番環境では長すぎる。しかし、短すぎると負荷スパイクだけでフェイルオーバーが走る。

  • 計算式: `(Redisの最大I/O待ち) + (ネットワークの往復時間) + マージン`
  • 多くの高負荷システムでは、5秒〜10秒程度に設定し、監視のメトリクス(`info replication`)とセットで調整する。
  • スワップの恐怖:

Redisはメモリ上で動く。OSのメモリが不足し、Redisの一部がディスク(スワップ)に吐き出された瞬間、レスポンスは数秒単位で止まる。Sentinelはこれを「マスターダウン」と誤検知する。
アーキテクトの戒め: `vm.swappiness = 0` は必須。これなしでRedisを運用するのは、砂上の楼閣を建てるようなものだ。

—

4. 堅牢な設計パターンのための「チェックリスト」

私がコードレビューで必ず確認する項目を伝授する。

1. Proxyの排除:
Sentinel環境でEnvoyやHAProxyを挟む構成を好む者がいるが、それは複雑性を増すだけだ。クライアントライブラリがSentinelをサポートしているなら、直結させるのが最も低レイテンシで確実である。

2. 監視との分離:
Sentinelのログを監視して `+switch-master` や `+sdown` イベントを拾えるようにしておくこと。フェイルオーバーは「成功すればよし」ではなく、「なぜ起きたのか」を追跡できないと運用崩壊する。

3. クライアントの再試行戦略:
フェイルオーバー中、わずかに接続が切れる瞬間がある。アプリ側でリトライポリシー(指数バックオフ)を正しく実装していないと、その瞬間にリクエストが全滅する。

—

結論:Sentinelは「自動化」ではなく「保険」である

Sentinelは、マスターが死んだときに「最短で」系を切り替えるための仕組みであり、「障害が起きないようにする魔法」ではない。

結局のところ、最高の可用性は「Sentinelを信頼しすぎない」設計から生まれる。

  • データの整合性は保たれているか?
  • フェイルオーバー中の書き込みは防げているか?
  • クライアントは瞬時の切断を許容できる構造か?

Sentinelを単なる機能として導入するのではなく、インフラ全体を「壊れる前提」で設計する。そのマインドセットを持って初めて、貴方のRedisシステムは真の堅牢性を手に入れる。

さあ、コードを書き、そして徹底的に負荷をかけてくれ。Sentinelが意図通りに動くかどうかを、本番環境に投入する前に、自らの手で破壊して確かめることだ。それがエンジニアとしての唯一の近道である。

コメント

タイトルとURLをコピーしました