🙌
Docker Compose で MongoDB のレプリカセットを構築してみた
MongoDB のレプリカセットとは?
Gemini に聞いてみた
MongoDB のレプリカセットとは、データの冗長性と高可用性を提供する機能です。複数の MongoDB サーバー(ノード)で構築され、同一のデータセットを保持します。これにより、ハードウェア障害やネットワーク障害が発生した場合でも、データへのアクセスを継続できます。
レプリカセットの主な特徴
- データの冗長性
複数のノードが同一のデータを保持するため、1つまたは複数のノードが故障してもデータは失われない。 - 高可用性
Primary ノードがダウンした場合、自動的に Secondary ノードが Primary ノードに昇格し、サービスを継続する。 - 自動フェイルオーバー
Primary ノードの障害を検知し、自動的に新しい Primary ノードを選出する機能がある。 - 読み込みスケーラビリティ
Secondary ノードから読み込みを行うことで、読み込み処理を分散しパフォーマンスを向上させることができる。
レプリカセットの構成要素
- Primary ノード
- レプリカセットの中で唯一書き込みを受け付けるノード。
- 全ての書き込み操作は Primary ノードに集中し、そこから他の Secondary ノードにデータが複製される。
- クライアントからの読み込み要求も Primary ノードで処理されるが、設定によっては Secondary ノードからの読み込みも可能。
- Primary ノードがダウンした場合、レプリカセットは自動的に新しい Primary ノードを選出する。
- Secondary ノード
- Primary ノードからデータを複製し、データの冗長性を確保する。
- Primary ノードがダウンした場合、新しい Primary ノードの候補になる。
- 設定によっては、クライアントからの読み込み要求を処理することも可能。これにより、読み込み負荷を分散させることができる。
- 常に Primary ノードからの oplog を適用し、データの整合性を保つ。
- Arbiter ノード(必須ではない)
- データを持たない特殊なノードで、Primary ノードの選出にのみ参加する。
- データを持たないため、ディスクの容量を節約する。
- 主に、レプリカセットのノード数を奇数にするために使用される。これにより、Primary ノードの選出がより安定する。
- Arbiter は投票にのみ参加し、データの複製やクライアントからの読み込み要求を処理しない。
レプリカセットの動作
- データの複製
- Primary ノードで行われた書き込み操作は、oplog と呼ばれるログに記録される。
- Secondary ノードは、oplog を Secondary ノードから取得し、自身のデータに適用することで、Primary ノードと同一のデータを保持する。
- Primary ノードの選出
- Primary ノードがダウンした場合、レプリカセット内のノード間で選挙が行われ、新しいノードが選出される。
- 選挙には、各ノードの優先度やデータの状態などが考慮される。
レプリカセットを構築してみる
Docker や MongoDB の知識が未熟なので、必要最低限レプリカセットを構築できる設定となっています。
まずは MongoDB のコンテナを3つ用意するので、プロジェクトのルートに compose.yml
を作成する。
./compose.yml
services:
mongodb-primary:
image: mongo:7
container_name: mongodb-primary
hostname: mongodb-primary
# rs0 の部分は rs.initiate の _id と同じ値にする
command: ["mongod", "--replSet", "rs0", "--bind_ip_all"]
ports:
- "27017:27017"
networks:
- hoge-network
volumes:
# データの永続化
- mongodb-primary-data:/data/db
# レプリカセットの初期化処理を行うスクリプトをマウント
- ./docker/mongodb/init.js:/init.js
restart: always
depends_on:
- mongodb-secondary
- mongodb-arbiter
mongodb-secondary:
image: mongo:7
container_name: mongodb-secondary
hostname: mongodb-secondary
command: ["mongod", "--replSet", "rs0", "--bind_ip_all"]
networks:
- hoge-network
volumes:
# データの永続化
- mongodb-secondary-data:/data/db
restart: always
mongodb-arbiter:
image: mongo:7
container_name: mongodb-arbiter
hostname: mongodb-arbiter
command: ["mongod", "--replSet", "rs0", "--bind_ip_all"]
networks:
- hoge-network
restart: always
networks:
hoge-network:
volumes:
mongodb-primary-data:
mongodb-secondary-data:
レプリカセットの初期化処理を行うために、init.js
ファイルを作成して rs.initiate
を書く。
./docker/mongodb/init.js
rs.initiate({
_id: "rs0",
members: [
// コンテナの hostname と port を指定
// priority は優先順位を決める値(任意)
{ _id: 0, host: "mongodb-primary:27017", priority: 100 },
{ _id: 1, host: "mongodb-secondary:27017", priority: 10 },
// arbiterOnly: true で Arbiter ノードになる
{ _id: 2, host: "mongodb-arbiter:27017", arbiterOnly: true },
],
});
コンテナを起動する。
docker compose up -d
mongodb-primary
コンテナでレプリカセットの初期化を行う。
docker exec -i mongodb-primary mongosh /init.js
レプリカセットになっているか mongodb-primary
コンテナの中で mongosh
に接続して確認してみる。
docker compose exec mongodb-primary mongosh
rs0 [direct: primary] test>
と表示されていればレプリカセットの構築ができている。
Discussion