MongoDB レプリカセット + シャーディングの構築
症状
目標: MongoDB の自動フェイルオーバー付きレプリカセットを構築し、水平スケーリングのためにシャードクラスタに拡張する。
1. 同じ replSet 名で mongod プロセスを起動する
各レプリカセットメンバーを同じ --replSet 名と到達可能な --bind_ip で起動する。本番では keyFile または TLS による内部認証が推奨される。明確な過半数のため、投票メンバーは奇数にする。
MongoDB
mongod --replSet rs0 --port 27017 --dbpath /data/n1 --bind_ip localhost,10.0.0.11
mongod --replSet rs0 --port 27017 --dbpath /data/n2 --bind_ip localhost,10.0.0.12
mongod --replSet rs0 --port 27017 --dbpath /data/n3 --bind_ip localhost,10.0.0.132. レプリカセットを初期化する
mongosh で 1 つのメンバーに接続し、rs.initiate() を呼び出してすべてのメンバーを定義する。これにより最初の選出が起動され、プライマリが選ばれる。rs.status() で PRIMARY/SECONDARY のロールを確認する。
MongoDB
rs.initiate({
_id: 'rs0',
members: [
{ _id: 0, host: '10.0.0.11:27017' },
{ _id: 1, host: '10.0.0.12:27017' },
{ _id: 2, host: '10.0.0.13:27017' }
]
})
rs.status()3. メンバーを追加し、優先度と必要なら arbiter を設定する
後からメンバーを rs.add() で追加する。priority はどのメンバーがプライマリになりやすいかを決める (0 = プライマリにならない)。arbiter は投票のみを行いデータを持たない。データノードが偶数の場合のタイブレーカーとして使われるが、データの安全性のためには実メンバーが好ましい。arbiter ベースのトポロジー (特に PSA) では、データノードがダウンすると majority の write concern を満たせず書き込みが待機する。5.0+ では arbiter を追加する前に、setDefaultRWConcern でクラスタ全体のデフォルト write concern を明示的に設定する必要がある場合がある。
MongoDB
rs.add({ host: '10.0.0.14:27017', priority: 0.5 })
// Arbiter only if really needed (a data-bearing member is preferred):
rs.addArb('10.0.0.15:27017')
// change priority:
cfg = rs.conf(); cfg.members[0].priority = 2; rs.reconfig(cfg)4. シャーディング用に config サーバーのレプリカセットを構築する
シャードクラスタのメタデータは config サーバーのレプリカセット (--configsvr) に保持される。それ自体もレプリカセットとして初期化され、高可用性のため 3 メンバーが推奨される。
MongoDB
mongod --configsvr --replSet cfgrs --port 27019 --dbpath /data/cfg1 --bind_ip localhost,10.0.0.21
-- mongosh (on the config server):
rs.initiate({ _id: 'cfgrs', configsvr: true, members: [
{ _id: 0, host: '10.0.0.21:27019' },
{ _id: 1, host: '10.0.0.22:27019' },
{ _id: 2, host: '10.0.0.23:27019' } ] })5. シャードのレプリカセットと mongos ルーターを起動する
各シャードは --shardsvr で起動された独立したレプリカセットである (データの永続性はシャード内のレプリケーションによる)。mongos ルーターは config サーバーを指定して起動し、アプリケーションは mongos に接続する。
MongoDB
mongod --shardsvr --replSet shard1rs --port 27018 --dbpath /data/s1 --bind_ip localhost,10.0.0.31
# initiate shard1rs with rs.initiate, then mongos:
mongos --configdb cfgrs/10.0.0.21:27019,10.0.0.22:27019,10.0.0.23:27019 --port 27017 --bind_ip localhost,10.0.0.406. シャードを追加し、コレクションをシャーディングする
mongos に接続し、sh.addShard() で各シャードのレプリカセットを追加する。データベースでシャーディングを有効にし、sh.shardCollection() でシャードキーによりコレクションを分散する。キーの選択は重要である: 高いカーディナリティと均等な分布を持つべきである。sh.status() でチャンクの分布を監視する。
MongoDB
sh.addShard('shard1rs/10.0.0.31:27018')
sh.addShard('shard2rs/10.0.0.32:27018')
sh.enableSharding('appdb')
sh.shardCollection('appdb.events', { customer_id: 'hashed' })
sh.status()