【テクニカル・上級編】 レプリケーションアーキテクチャ – Redis

Redisレプリケーションの深淵:非同期の美学と「完全性」の代償

Redisのレプリケーションを単なる「データのコピー」と呼ぶのは、エンジニアとしてあまりに短絡的だ。これは、メモリ上の単一スレッド・イベントループという「制約」の中で、いかにして高可用性とスケーラビリティを両立させるかという、分散システムにおける極めて洗練された回答である。

本稿では、レプリケーションの表面的な設定ではなく、Redisが内部で何を考え、どのようなトレードオフを行っているのか、その深層に切り込む。

—

1. 複製プロトコルの本質:PSYNCの進化

Redisのレプリケーションにおいて最も重要なのは、`PSYNC`(Partial Resynchronization)の設計思想だ。

かつての `SYNC` コマンドは、レプリカが接続されるたびにマスター側で `BGSAVE` を実行し、全データセットをRDBファイルとして転送していた。これはI/OとCPUを強烈に消費する。対して `PSYNC` は、以下の3つの要素を管理することで、最小限の差分更新を実現する。

  • レプリケーションID: どのマスターに属しているか。
  • レプリケーションオフセット: どこまでデータが流れたか。
  • レプリケーションバックログ(Replication Buffer): 過去の更新ログを保持するリングバッファ。

なぜバックログサイズが「神の領域」なのか

`repl-backlog-size` を適切に見積もることは、システムアーキテクトの腕の見せ所だ。このバッファが小さいと、ネットワークの一時的な瞬断だけで「完全同期(Full Resynchronization)」がトリガーされ、マスターの負荷がスパイクする。

極限の知見:
バックログは `(マスターが秒間に処理する書き込み量) × (復旧に要する最大時間)` で計算すべきではない。さらに「RDB生成から転送完了までの間に発生する書き込み量」を上乗せしなければ、無限ループのように全同期が繰り返されるデッドロックに近い状況に陥る。

—

2. 非同期転送の「不整合」と向き合う

Redisのレプリケーションは「非同期(Asynchronous)」である。これはパフォーマンスを極限まで引き出すための代償だ。マスターがクライアントに `OK` を返すとき、レプリカへの転送は完了していない。

この設計がもたらすリスクを回避するため、真のアーキテクトは `WAIT` コマンドを適切に使いこなす。

2台のレプリカが同期を確認するまで、マスターはコマンドをリターンしない
WAIT 2 5000
2: 待機するレプリカ数
5000: タイムアウト(ミリ秒)

これにより、Redisは「結果整合性」から「準同期」へとステートを遷移させる。ただし、`WAIT` の過剰な使用はマスターの応答レイテンシを直接的に悪化させるため、厳密なデータ整合性が必要なパスでのみ局所的に適用するのが定石である。

—

3. レプリカの昇格:SentinelとClusterの思想

マスターが沈んだとき、レプリカを昇格させるプロセスは「合意形成」のドラマだ。

  • Redis Sentinel: 外部監視エージェントによる投票システム。ネットワーク分断(Split-brain)を考慮し、クォーラム(過半数)を重視する。
  • Redis Cluster: シャーディングとレプリケーションを統合したモデル。各ノードがゴシッププロトコルで状態を共有する。

特筆すべきは、昇格時の「古いマスターの再接続処理」である。昇格後に古いマスターが復帰した場合、`REPLICAOF` コマンドを自動発行し、レプリカとして再配置するまでがRedisの自己修復プロセスだ。この際、`min-replicas-to-write` 設定を怠ると、マスターが単独で書き込みを受け続け、データが乖離するリスクがあることを忘れてはならない。

—

4. アーキテクトへの提言:メモリ最適化の罠

レプリケーションを有効にすると、マスターのメモリ消費は加速する。なぜなら、各レプリカとの接続ごとに `Client Buffer` が割り当てられるからだ。

特に、全同期(Full Resynchronization)が発生する際、RDBをメモリ上に展開しつつ、その間の書き込みを `Replication Buffer` に蓄積するため、「マスターのメモリ使用量が急激に跳ね上がる」という現象が起きる。

実践的チューニングの指針

1. Replica-ignore-maxmemory: レプリカ側でのメモリ制限を無効化せよ。レプリカがキーをエビクション(削除)し始めると、マスターとのデータ整合性が崩壊し、論理的な不整合が発生する。
2. 出力バッファの制限: `client-output-buffer-limit replica` を調整し、レプリカが遅延しすぎた際に接続を切断する閾値を最適化せよ。遅延したレプリカを無理に保持することは、マスターのメモリを枯渇させる自殺行為である。

—

結びに代えて

Redisのレプリケーションは、ただの「機能」ではない。それは、メモリという揮発性で高速なリソースを、いかにして「永続的かつ堅牢な分散エンジン」に昇華させるかという挑戦の歴史だ。

マニュアルにある設定項目を埋めるだけで満足してはならない。その裏で動くPSYNCのオフセット管理、バックログのリングバッファ、そして非同期ゆえの「見えない遅延」を常にイメージすること。それこそが、Redisを使いこなす唯一の道である。

次回の記事では、`Redis Cluster` のハッシュスロット分散と、内部的な `ASK/MOVED` リダイレクトの極限最適化について深掘りする。準備を怠るな。

コメント

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