Redis のシンプルな主従(マスター・スレーブ)レプリケーションには、以下のような制限がある。
- マスターは読み書き可能だが、スレーブは読み取り専用
- マスターが停止した場合、自動フェイルオーバーは行われず、手動での再設定が必要
本記事では、Docker を用いた Redis 6.2.6 の主従構成のセットアップと、上記課題の検証を行う。
設定ファイルの準備
まず、GitHub から Redis 6.2.6 向けの redis.conf を取得し、以下の設定を変更する。
#bind 127.0.0.1 -::1→ コメントアウト(外部アクセス許可)protected-mode no(保護モード無効化)appendonly yes(AOF 永続化有効)daemonize no(Docker 環境ではデフォルトのまま)
Docker コンテナの起動
マスターとスレーブ用にそれぞれディレクトリを作成し、設定ファイルとデータディレクトリをマウントしてコンテナを起動する。
docker run -p 6380:6379 \
--restart=always \
--log-opt max-size=1024m --log-opt max-file=2 \
--name redis-master \
--privileged=true \
-v /path/to/master/redis.conf:/etc/redis/redis.conf \
-v /path/to/master/data:/data \
-d redis redis-server /etc/redis/redis.conf
docker run -p 6381:6379 \
--restart=always \
--log-opt max-size=1024m --log-opt max-file=2 \
--name redis-slave \
--privileged=true \
-v /path/to/slave/redis.conf:/etc/redis/redis.conf \
-v /path/to/slave/data:/data \
-d redis redis-server /etc/redis/redis.conf
主従関係の設定
スレーブ側で主従関係を設定する方法は2つある。
1. 設定ファイルによる方法
スレーブの redis.conf に以下を追加:
replicaof 192.168.0.168 6380
2. コマンドラインによる方法
スレーブコンテナ内で以下を実行:
redis-cli
> replicaof 192.168.0.168 6380
主従関係を解除するには:
> replicaof no one
動作検証
.NET Core アプリケーションから StackExchange.Redis を使用し、スレーブへの書き込みを試みるとエラーが発生し、読み取り専用であることが確認できる。
また、マスター停止後にスレーブを再起動すると、主従関係が解除され、スレーブがスタンドアロンモードになる。この状態でデータを書き込んだ後、元のマスターを復旧させてスレーブとして再接続しても、データの自動同期は行われない。
データ同期の挙動
初回のレプリケーションはフル同期(full sync)で行われる。この際、スレーブの既存データはすべて削除され、マスターの RDB スナップショットが転送される。検証の結果、スレーブに手動で追加したキーは同期時に消失することが確認された。
その後の更新は、増分同期(partial sync)により、コマンドログ(replication backlog)に基づいて同期される。
システム設定の注意点
Docker 環境で Redis を起動する際、以下のような警告が出ることがある。
WARNING overcommit_memory is set to 0!
これを解消するには、ホストOSで以下を実行する必要がある。
sysctl vm.overcommit_memory=1