午前2時の呼び出し:なぜ単一ノードのRedisは失敗するのか
午前2時14分。枕元でスマホが激しく震えている。PagerDutyの通知が鳴り止まない。本番環境のAPIが90%の割合で500エラーを吐き出しているからだ。眠い目をこすりながらデスクに向かうと、単一のRedisインスタンスがOOM(メモリ不足)キラーに遭遇し、消滅していることがわかった。スタンドアロンノードだったため、セッションデータは失われていた。手動でサービスを再起動し、12GBのRDBファイルがロードされるのを4分間待ち、データが破損していないことを祈るししかわかった。
このような経験をしたことがあるなら、「単一障害点(Single Point of Failure)」が単なるDevOpsのプレゼンスライド上の言葉ではないことを知っているはずだ。それは睡眠不足とユーザーの不満を招く原因となる。堅牢なシステムを構築するには、単一のインスタンスから脱却する必要がある。Redisの世界では、それは Redis Sentinel と Redis Cluster という2つの異なるアーキテクチャのどちらかを選択することを意味する。
Sentinel vs. Cluster: どちらを選ぶべきか
開発者がこれらを同じものの別バージョンとして扱っているのをよく見かけるが、そうではない。可用性が必要なのか、それとも純粋な容量が必要なのかによって、解決する問題が根本的に異なる。
Redis Sentinel: 高可用性のスペシャリスト
Sentinelは、データベースの外に立つ「見張り番」のグループだと考えてほしい。彼らの唯一の仕事は、PrimaryノードとReplicaノードを監視することだ。Primaryが30秒以上応答を停止すると、Sentinelたちは選挙を行う。健全なReplicaを1つ選び、それを新しいPrimaryに昇格させる。アプリケーションはSentinelに問い合わせて、新しいIPアドレスを取得する。これは信頼性のために構築されたものであり、大規模な拡張を目的としたものではない。
Redis Cluster: スケーリングの原動力
Redis Clusterはシャーディングがすべてだ。データは16,384個のハッシュスロットに分割され、複数のノードに分散される。150GBのデータがある場合、それを50GBのノード3つに分散させることができる。各シャードに独自のReplicaを持たせることで高可用性も提供する。しかし、その主な目的は水平スケーリング、つまり単一のCPUコアでは処理できないような毎秒数百万件のリクエストを処理することにある。
メリットとデメリット:高可用性 vs 水平スケーリング
万能な解決策はない。設定ファイルに触れる前に、運用上のトレードオフを検討する必要がある。
Redis Sentinel
- メリット: セットアップと管理が非常に簡単。確実な自動フェイルオーバーを提供。JedisやStackExchange.Redisなど、ほとんどの標準的なクライアントライブラリがSentinelの切り替えをネイティブにサポートしている。
- デメリット: 依然として1台のマシンのRAM容量に制限される。セットアップ内のすべてのノードがデータセット全体の完全なコピーを保持する。書き込みを単一ノード以上にスケールさせることはできない。
Redis Cluster
- メリット: 圧倒的なスケーラビリティ。必要に応じてクラスタを1,000ノードまで拡張可能。データは自動的にパーティショニングされるため、特定のノードがボトルネックになることはない。
- デメリット: 運用上の複雑さが格段に高い。MGETや複雑なトランザクションなどの複数キー操作は、キーが異なるシャードに存在する場合、制限される。安定した本番環境のセットアップには、少なくとも6つのノード(Primary 3つ、Replica 3つ)が必要。
最近のプロジェクトで、大規模なレガシーデータセットをCSVファイルからRedis Clusterに移行する必要があった。このようなインポート作業でCSVをJSONに素早く変換したいときは、toolcraft.app/ja/tools/data/csv-to-json を使っている。ブラウザ上で完結するため、機密性の高い本番データがマシン外に出ることはない。これはセキュリティコンプライアンスの観点から大きな利点だ。
本番環境に推奨されるセットアップ
データセットは64GB未満だろうか?もし標準的なクラウドインスタンスのRAMに余裕を持って収まるなら、Redis Sentinel が一番の選択肢だ。午前2時にトラブルが発生した際、デバッグがはるかに容易だからだ。ハッシュスロットの管理に頭を悩ませることなく、フェイルオーバーの安全性というメリットを享受できる。
しかし、データが毎日5GBずつ増えるようなリアルタイム分析プラットフォームを構築しているとしたらどうだろう?その場合は Redis Cluster が唯一の道だ。本番環境では、Sentinelノードは3つ以上、ClusterのPrimaryノードも3つ以上で運用すること。それ以下だと「スプリットブレイン(Split Brain)」のリスクがある。これは2つのノードが両方とも自分をリーダーだと思い込んでしまう現象で、不可避的にデータの破損を招く。
ステップバイステップ:Redis Sentinelの実装
基本的なSentinel環境を構築してみよう。Primary(192.168.1.10)が1台、Replica(192.168.1.11)が1台あると想定する。
1. Replicaの設定
Replicaサーバーで、redis.conf を編集してPrimaryノードに従うように設定する:
# 192.168.1.11 の redis.conf
replicaof 192.168.1.10 6379
2. Sentinelノードの設定
多数決による合意を確実にするため、少なくとも3つの別々のVMでSentinelを実行する。それぞれのマシンに sentinel.conf ファイルを作成する:
# sentinel.conf
port 26379
daemonize yes
# monitor <マスター名> <IPアドレス> <ポート> <クォーラム>
sentinel monitor mymaster 192.168.1.10 6379 2
# 5秒間応答がない場合、マスターが「ダウン」したとみなす
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
「クォーラム(quorum)」の 2 は極めて重要だ。これは、昇格プロセスを開始する前に、2つのSentinelがPrimaryがダウンしたと同意する必要があることを意味する。起動コマンド: redis-sentinel /path/to/sentinel.conf
スケールアウト:Redis Clusterのセットアップ
メモリ制限に達しているなら、水平スケーリングの出番だ。最小構成のクラスタには3つのPrimaryノードが必要。安全のため、それぞれに1つのReplicaも追加する。
1. クラスタモードの有効化
6つのノードすべてで、redis.conf を以下の行で更新する:
port 6379
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
2. クラスタの作成
インスタンスが起動したら、Redis CLIを使用してそれらを結合する。このコマンドは、いずれか1つのノードから一度だけ実行すればよい:
redis-cli --cluster create \
192.168.1.10:6379 192.168.1.11:6379 192.168.1.12:6379 \
192.168.1.13:6379 192.168.1.14:6379 192.168.1.15:6379 \
--cluster-replicas 1
--cluster-replicas 1 フラグは、すべてのPrimaryに1つのバックアップを作成することを保証する。Redisは16,384個のスロットを3つのPrimaryに自動的に分配する。
3. シャードの確認
以下のコマンドでクラスタの状態を確認する:
redis-cli -c -p 6379
cluster nodes
ここでもっとも重要なのは -c フラグだ。これによりCLIで「クラスタモード」が有効になる。これにより、探しているキーが別のシャードにある場合に、ツールがリダイレクトに従うことができるようになる。
分散環境への移行は、最初は難しく感じるかもしれない。しかし、それによって得られる安心感は、その労力に見合うものだ。コーヒーを飲んでいる間にSentinelノードが自動的にReplicaを昇格させるのを見れば、もうスタンドアロンインスタンスには戻れなくなるだろう。まずはシンプルにSentinelから始め、データの増加に応じてClusterへの移行を検討してほしい。

