レプリケーション

Redis のレプリケーションでは、マスター・スレーブ型のレプリケーションを簡易に設定できます。マスター・スレーブ型レプリケーションでは、スレーブサーバーはマスターサーバーの正確なコピーになります。以下は、Redis レプリケーションについての、いつくかの重要なポイントです。

Redis のレプリケーションはどのように動作しているか

スレーブがセットアップされたら、スレーブは接続を通じて SYNC コマンドを送ります。初回の接続でも再接続でも同じです。

マスターはバックグラウンド・セーブを開始し、また、以降に受信する、データ・セットを変更するすべてのコマンドのバッファを始めます。バックグラウンド・セーブが完了したら、マスターはデータベースファイルをスレーブに転送し、スレーブはそれをディスクに保存、およびメモリへロードします。その後、マスターはすべてのバッファされたコマンドをスレーブに送信します。これはコマンドのストリームとして実現されていて、Redis プロトコルそのものと同じフォーマットをもちます。

telnet 経由で、自分で試してみることもできます。稼働中の Redis サーバーのポートに接続し、 SYNC コマンドを発行してください。まずバルク転送と、その後マスターが受信したすべてのコマンドが telnet セッションを通じて発行されることが確認できるでしょう。

スレーブは、マスター・スレーブ間の接続が何らかの原因でダウンしたとき、自動的に再接続を行います。マスターは複数のスレーブから同時に同期リクエストを受け付けた場合、1 度のバックグラウンド・セーブのみを実行して、全スレーブの要求に応答します。

あるマスターとスレーブが接続ダウン後に再接続した場合は、常にフル同期が実行されます。ただし、Redis 2.8 からは、partial resynchronization も可能になりました。

Partial resynchronization

Redis 2.8 以降では、レプリケーションの接続が途切れた後、フル再同期を行うことなく、レプリケーションプロセスを継続できるようになりました。

これは、レプリケーション・ストリームのバックログを、マスター側のメモリ上に作成しておくことで実現されます。マスターとすべてのスレーブは、 replication offsetmaster run id について同意をとります。そして接続がダウンしたときは、スレーブは再接続を行い、マスターにレプリケーション再開を要求します。もし master run id がまだ同じで、 offset がレプリケーション・バックログから入手可能なら、レプリケーションは最後に途切れたポイントから再開されます。もし条件のいずれかが満たされなければ、フル再同期が行われます(2.8 以前の振る舞いと同じです)。

新しい partial resynchronization 機能は、内部的に PSYNC コマンドを使っていて、一方古い実装では SYNC コマンドを使っています。Redis 2.8 のスレーブは、接続先サーバーが PSYNC をサポートしているかを検知して、サポートしていなければ代わりに SYNC を使うことに留意してください。

設定

レプリケーションの設定は簡単です: スレーブの設定ファイルに以下の行を追加してください:

slaveof 192.168.1.1 6379

もちろん、192.168.1.1 6379 をあなたのマスターのIPアドレス(またはホスト名)とポートに読み替えてください。別のやり方として、 SLAVEOF コマンドを発行する方法もあります。コマンドが発行されると、マスターはスレーブとの同期を開始します。

partial resynchronization を実行するため、マスターのメモリ上にレプリケーション・バックログが置かれますが、それをチューニングするいくつかのパラメータがあります。 詳しくは、Redis 配布モジュールに同梱されている redis.conf の例を参照してください。

Read-only スレーブ

Redis 2.6 以降、スレーブは read-only モード(デフォルト有効) をサポートします。この振る舞いは、redis.conf ファイルの slave-read-only オプションで制御されます。また、 CONFIG SET を使ってランタイムに有効化/無効化できます。

read-only のスレーブはすべての書き込みコマンドを拒否するため、間違えてスレーブに書き込んでしまう、ということが不可能になります。この機能は、インターネット、より一般的にいうと、信頼できないクライアントが存在するネットワーク上にスレーブを公開することを意図するものではありません。 DEBUGCONFIG といった管理コマンドは有効なままのためです。しかし、redis.conf の rename-command ディレクティブによりコマンドを無効化することで、read-only インスタンスのセキュリティを向上できます。

スレーブが書き込みを受け付けるように read-only 設定を無効にできるのはなぜか、不思議に思うかもしれません。マスターとスレーブが再同期するとこれらの書き込みは破棄される一方で、書き込み可能なスレーブに、ごく短命なデータを格納しておくのが合理的なユースケースがあります。たとえば、フェイルオーバー戦略のコーディネートのため、マスターへ到達可能かの情報を、クライアントが書き込むことができます。

マスターの認証設定

マスターに requirepass でパスワードが設定されている場合、すべての同期操作のために、スレーブ側にそのパスワードを設定することは簡易です。

実行中のインスタンスに対しては、 redis-cli で接続して以下をタイプしてください:

config set masterauth <password>

これを永続的に設定するには、設定ファイルに以下を追記してください:

masterauth <password>

N 個のレプリカが所属している場合にかぎり書き込みを許可する

Redis 2.8 以降、マスターに最低 N スレーブが接続している場合にかぎり、書き込み要求を受け付ける設定が可能になりました。

しかしながら、Redis は非同期レプリケーションを採用しているため、スレーブが本当に書き込み要求を受信したかを知ることは不可能です。そのため、データ・ロスの時間ウィンドウは常に存在します。

この機能は以下のように動作します:

  • Redis スレーブはマスターに対し毎秒 ping を送信し、レプリケーション・ストリームを受信します。

  • Redis マスターは各スレーブについて、最後に受信した ping の時刻を覚えておきます。

  • ユーザーは、ある(最大秒数を超えない範囲の)タイムラグとともに、最小スレーブ数を設定することができます。

M 秒よりも小さなタイムラグの間に、最低 N スレーブが存在するなら、書き込みは受け付けられます。

これは CAP 定理の “C” を緩和したバージョンと考えることができます: ある書き込みに対する一貫性は保証されないが、少なくともデータロスの時間ウィンドウは指定された秒数までに制限される。

もし条件が満たされなければ、マスターはエラーを返し、書き込みは受け付けられません。

この機能の設定のために、2 つの設定パラメータがあります:

  • min-slaves-to-write <number of slaves>
  • min-slaves-max-lag <number of seconds>

より詳しい情報については、Redis 配布モジュールに同梱されている redis.conf の例を参照してください。