概要
気づいたらMongoDBも4.2になっていました。
以前に
DockerでMongoDBのレプリカセットを構築 - Carpe Diem
でレプリケーションを、
でシャーディングを構築しましたが、設定項目が代わっていたりしたので復習がてらdocker上で構築検証しました。
大まかな流れは変わらないため、↑の記事を読んでおくとスムーズに進められます。
環境
- MongoDB 4.2
- Docker 19.03.2
クラスタ構成
種類 | レプリカ名 | 台数 |
---|---|---|
config | configRepl | 3 |
mongod shard | shardRepl_1 | 3 |
mongod shard | shardRepl_2 | 3 |
mongod shard | shardRepl_3 | 3 |
mongos | - | 1 |
の計13台です。
以下のような形です。
検証コード
この検証で使っているコードは以下です。
設定
各設定を順に説明していきます。
docker-compose.yml
まずdocker-composeです。
Config server
基本的に起動時にconfigを指定する形式にしておきます。
mongoc001: &mongoc container_name: mongoc001 image: mongo:4.2 networks: - mongo_net volumes: - ./mongoc.conf:/etc/mongoc.conf command: mongod --config /etc/mongoc.conf mongoc002: <<: *mongoc container_name: mongoc002 mongoc003: <<: *mongoc container_name: mongoc003
mongoc.conf
設定ファイルは以下です。
sharding: clusterRole: configsvr replication: replSetName: configRepl net: port: 27019 bindIp: 0.0.0.0 storage: dbPath: /data/configdb journal: enabled: true
ポイントはbindIp
を0.0.0.0
にしているところです。MongoDB 3.6からデフォルトだとlocalhostになっており、疎通ができなくなります。
※dockerでは開発しやすいよう引数与えないと自動で0.0.0.0
になります。
bindipって何?という方は以下を参考にしてください。
bindアドレスとadvertiseアドレス - Carpe Diem
また3.4からconfigサーバでレプリカセットを組むことが必須になっているので、replicationの設定もしています。
configsvrのデフォルトポートは27019
なのでそれを指定します。
Mongod shard server
こちらも先程のように各シャード毎にレプリカセットを組めるように用意します。
mongod001: &shardRepl_1 container_name: shardRepl_1_001 image: mongo:4.2 networks: - mongo_net volumes: - ./mongod_1.conf:/etc/mongod.conf command: mongod --config /etc/mongod.conf mongod002: <<: *shardRepl_1 container_name: shardRepl_1_002 mongod003: <<: *shardRepl_1 container_name: shardRepl_1_003 mongod004: &shardRepl_2 <<: *shardRepl_1 container_name: shardRepl_2_001 volumes: - ./mongod_2.conf:/etc/mongod.conf mongod005: <<: *shardRepl_2 container_name: shardRepl_2_002 mongod006: <<: *shardRepl_2 container_name: shardRepl_2_003 mongod007: &shardRepl_3 <<: *shardRepl_1 container_name: shardRepl_3_001 volumes: - ./mongod_3.conf:/etc/mongod.conf mongod008: <<: *shardRepl_3 container_name: shardRepl_3_002 mongod009: <<: *shardRepl_3 container_name: shardRepl_3_003
mongod_n.conf
先程と似ていますが、clusterRole: shardsvr
となっています。
またシャード毎にレプリカセットを用意するため別ファイルにしています。
これは1つめのシャードの設定なのでreplSetName: shardRepl_1
となっています。
sharding: clusterRole: shardsvr replication: replSetName: shardRepl_1 net: port: 27018 bindIp: 0.0.0.0 storage: dbPath: /data/db journal: enabled: true
shardsvrのデフォルトポートは27018
なのでそれを使います。
Mongos
mongosの起動時はmongod
でなくmongos
です。
またmongosのみport forward設定しています。
mongos001: container_name: mongos001 image: mongo:4.2 networks: - mongo_net volumes: - ./mongos.conf:/etc/mongos.conf command: mongos --config /etc/mongos.conf ports: - "27017:27017"
mongs.conf
sharding: configDB: configRepl/mongoc001:27019,mongoc002:27019,mongoc003:27019 net: port: 27017 bindIp: 0.0.0.0
ポイントはsharding.configDB
でconfigサーバのレプリカセットを指定している点です。
起動後の設定
上記をdocker-composeで起動した後の設定をしていきます。
Config server
コンテナに入って
$ docker exec -it mongoc001 mongo --port 27019
レプリケーション設定を行います。
> config = { "_id": "configRepl", "members": [ {"_id": 0, "host": "mongoc001:27019"}, {"_id": 1, "host": "mongoc002:27019"}, {"_id": 2, "host": "mongoc003:27019"} ] } > rs.initiate(config)
Mongod shard server
同様にレプリカセットを構築しますが、PSAアーキテクチャ
ではなく、Secondaryが2つの形にします。
理由は3.6から細かく設定できるようになったRead concernのデフォルトがmajority
なのですが、PSA構成だとダウン時にstorage cacheが増加しパフォーマンスに影響が出るためOFFにした方が良いようです。
しかしRead concernの推奨としてはmajority
なので、Secondary2台構成にします。
IMPORTANT
In general, avoid disabling "majority" read concern unless necessary. However, if you have a three-member replica set with a primary-secondary-arbiter (PSA) architecture or a sharded cluster with a three-member PSA shard, disable to prevent the storage cache pressure from immobilizing the deployment.
ref: https://docs.mongodb.com/manual/reference/read-concern-majority/#disable-read-concern-majority
shardRepl_1
同様にコンテナに入って
$ docker exec -it shardRepl_1_001 mongo --port 27018
レプリケーション設定を行います。
> config = { "_id": "shardRepl_1", "members": [ {"_id": 0, "host": "shardRepl_1_001:27018"}, {"_id": 1, "host": "shardRepl_1_002:27018"}, {"_id": 2, "host": "shardRepl_1_003:27018"} ] } > rs.initiate(config)
他のレプリカセットも同様に設定します。
shardRepl_2
$ docker exec -it shardRepl_2_001 mongo --port 27018
> config = { "_id": "shardRepl_2", "members": [ {"_id": 0, "host": "shardRepl_2_001:27018"}, {"_id": 1, "host": "shardRepl_2_002:27018"}, {"_id": 2, "host": "shardRepl_2_003:27018"} ] } > rs.initiate(config)
shardRepl_3
$ docker exec -it shardRepl_3_001 mongo --port 27018
> config = { "_id": "shardRepl_3", "members": [ {"_id": 0, "host": "shardRepl_3_001:27018"}, {"_id": 1, "host": "shardRepl_3_002:27018"}, {"_id": 2, "host": "shardRepl_3_003:27018"} ] } > rs.initiate(config)
Mongos server
mongosはポートフォワーディングしているのでそのままアクセスできます。
$ mongo localhost:27017
シャードの登録
mongodをshardとして登録します。
レプリカセットの全サーバを入れる必要はなく、1つだけ指定しておけば大丈夫です。
mongos> sh.addShard("shardRepl_1/shardRepl_1_001:27018") mongos> sh.addShard("shardRepl_2/shardRepl_2_001:27018") mongos> sh.addShard("shardRepl_3/shardRepl_3_001:27018")
確認します。
mongos> sh.status() --- Sharding Status --- sharding version: { "_id" : 1, "minCompatibleVersion" : 5, "currentVersion" : 6, "clusterId" : ObjectId("5d84899c781951790530e119") } shards: { "_id" : "shardRepl_1", "host" : "shardRepl_1/shardRepl_1_001:27018,shardRepl_1_002:27018,shardRepl_1_003:27018", "state" : 1 } { "_id" : "shardRepl_2", "host" : "shardRepl_2/shardRepl_2_001:27018,shardRepl_2_002:27018,shardRepl_2_003:27018", "state" : 1 } { "_id" : "shardRepl_3", "host" : "shardRepl_3/shardRepl_3_001:27018,shardRepl_3_002:27018,shardRepl_3_003:27018", "state" : 1 }
登録されてます。
有効化
logdb
というDBに対してシャーディングを有効化します。
mongos> sh.enableSharding("logdb")
シャードindexの追加
次にコレクションに対してシャードキーの設定をします。
users
というコレクションの_idフィールドに設定することにします。
mongos> sh.shardCollection("logdb.users", {"_id": 1})
動作確認
検証時にシャーディングのバランシングがされやすいよう、chunkSizeを変更しておきます。
3.4からsharding.chunkSizeはconfigファイルの設定項目から消えているので注意してください。
mongos> use config switched to db config mongos> db.settings.save({ _id:"chunksize", value: 1}) WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : "chunksize" })
データ投入
ループでダミーデータを入れます。
mongos> use logdb mongos> for (var i = 1; i <= 100000; i++) { db.users.insert({number: i , name: "foo"+i}) }
バランシング確認
ちゃんとバランシングされていることが分かります。
mongos> sh.status() --- Sharding Status --- ... autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: no Failed balancer rounds in last 5 attempts: 0 Migration Results for the last 24 hours: 5 : Success databases: ... { "_id" : "logdb", "primary" : "shardRepl_2", "partitioned" : true, "version" : { "uuid" : UUID("ea5a63e9-b9cd-4629-8201-0f596a5c5924"), "lastMod" : 1 } } logdb.users shard key: { "_id" : 1 } unique: false balancing: true chunks: shardRepl_1 3 shardRepl_2 3 shardRepl_3 3 { "_id" : { "$minKey" : 1 } } -->> { "_id" : ObjectId("5d848f3c1cd4a5e8cfb6f796") } on : shardRepl_3 Timestamp(6, 1) { "_id" : ObjectId("5d848f3c1cd4a5e8cfb6f796") } -->> { "_id" : ObjectId("5d848f611cd4a5e8cfb740ba") } on : shardRepl_1 Timestamp(5, 1) { "_id" : ObjectId("5d848f611cd4a5e8cfb740ba") } -->> { "_id" : ObjectId("5d848f751cd4a5e8cfb7654c") } on : shardRepl_2 Timestamp(4, 1) { "_id" : ObjectId("5d848f751cd4a5e8cfb7654c") } -->> { "_id" : ObjectId("5d848f911cd4a5e8cfb79688") } on : shardRepl_2 Timestamp(3, 3) { "_id" : ObjectId("5d848f911cd4a5e8cfb79688") } -->> { "_id" : ObjectId("5d848faa1cd4a5e8cfb7bb1a") } on : shardRepl_1 Timestamp(4, 2) { "_id" : ObjectId("5d848faa1cd4a5e8cfb7bb1a") } -->> { "_id" : ObjectId("5d848fcb1cd4a5e8cfb7ecd2") } on : shardRepl_1 Timestamp(4, 3) { "_id" : ObjectId("5d848fcb1cd4a5e8cfb7ecd2") } -->> { "_id" : ObjectId("5d848fdf1cd4a5e8cfb81164") } on : shardRepl_3 Timestamp(5, 2) { "_id" : ObjectId("5d848fdf1cd4a5e8cfb81164") } -->> { "_id" : ObjectId("5d848ffb1cd4a5e8cfb84325") } on : shardRepl_3 Timestamp(5, 3) { "_id" : ObjectId("5d848ffb1cd4a5e8cfb84325") } -->> { "_id" : { "$maxKey" : 1 } } on : shardRepl_2 Timestamp(6, 0)