MongoDB Atlas への移行ツール:mongomirror を試してみた
こんにちは、菊池です。
MongoDB のマネージドサービス:MongoDB Atlasへのマイグレーションツール、mongomirrorを試してみましたのでレポートします。
Migrate with mongomirror | MongoDB Atlas
mongomirror
mongomirrorはオンプレやクラウド環境で稼働する、MongoDBのデータをMongoDB Atlasへ移行するツールです。
AWSのDatabase Migration Serviceのように、ワンタイムの一括コピーと、オンラインでの継続的レプリケーションの両方が可能です。
前提条件
ソースデータベース:
- MongoDB 3.0以降であること
- レプリカセット構成であること
ターゲットデータベース:
- MongoDB 3.4の最新版であること
- レプリカセットのAtlas Clusterであること
- 無償版以外のクラスタサイズ
レプリケーションで使われるOplogを利用する仕組みのためか、ソース/ターゲット共にレプリカセット構成であることが必須です。
また、mongomirrorを実行するインスタンスから、ソース/ターゲットの両方に接続可能である必要があります。
試してみた
早速試してみました。
ソースデータベース
まずはソースのデータ確認です。以下のように、main
データベースにusers
コレクションが存在しています。
s0-rs0:PRIMARY> use main switched to db main s0-rs0:PRIMARY> show collections users s0-rs0:PRIMARY> db.users.find() { "_id" : ObjectId("58dddfc7e87a9d84c86068ed"), "userid" : 10000, "name" : "hoge1", "age" : 19 } { "_id" : ObjectId("58dddfc7e87a9d84c86068ee"), "userid" : 20000, "name" : "hoge2", "age" : 33 } { "_id" : ObjectId("58dddfc7e87a9d84c86068ef"), "userid" : 30000, "name" : "hoge3", "age" : 41 } { "_id" : ObjectId("58dddfc7e87a9d84c86068f0"), "userid" : 40000, "name" : "hoge4", "age" : 24 } { "_id" : ObjectId("58dddfc7e87a9d84c86068f1"), "userid" : 50000, "name" : "hoge5", "age" : 50 } { "_id" : ObjectId("58dddfc8e87a9d84c86068f2"), "userid" : 60000, "name" : "hoge6", "age" : 16 } s0-rs0:PRIMARY>
マイグレーションに必要なbackup
ロールのユーザを作成します。
s0-rs0:PRIMARY> db.createUser( { user: "mySourceUser", pwd: "xxxxxxxx", roles: [ "backup" ] } ) Successfully added user: { "user" : "mySourceUser", "roles" : [ "backup" ] } s0-rs0:PRIMARY>
ターゲットデータベース
ターゲットデータベースは初期状態なのでデータが存在していません。
Cluster1-shard-0:PRIMARY> show dbs admin 0.000GB local 0.000GB Cluster1-shard-0:PRIMARY>
ターゲットデータベースとなるAtlasにも、マイグレーションに必要なユーザを準備しておきます。必要なロールはreadWriteAnyDatabase
とdbAdminAnyDatabase
です。今回はadmin
ユーザを利用しました。
mongomirrorの実行
mongomirrorのバイナリは公式からダウンロード可能です。今回はAmazonLinuxで実行しました。
ダウンロードしたmongomirrorを実行します。
$ mongomirror --host=s0-rs0/mongo1:27017,mongo2:27017,mongo3:27017 \ -u "mySourceUser" \ -p "xxxxxxxx" \ --authenticationDatabase=admin \ --destination=Cluster1-shard-0/cluster1-shard-00-01-xxxxxx.net:27017,cluster1-shard-00-01-xxxxxx.net:27017,cluster1-shard-00-02-xxxxxx.net:27017 \ --destinationUsername=skikuchi \ --destinationPassword=xxxxxxxx 017-03-31T05:20:17.029+0000 Creating collection main.users 2017-03-31T05:20:17.145+0000 Copying documents to collection main.users 2017-03-31T05:20:17.256+0000 Dumped 6 documents to main.users 2017-03-31T05:20:17.257+0000 Applying oplog entries that occurred during the initial sync, start: 6403528283916337153, end: 6403528283916337153 2017-03-31T05:20:17.267+0000 Tailing the oplog 2017-03-31T05:20:17.267+0000 Oplog tailer has shut down. Oplog applier will exit. 2017-03-31T05:20:17.373+0000 Current lag from source: 0s 2017-03-31T05:20:17.383+0000 Tailing the oplog
問題なければすぐに初期同期が完了します。ターゲット側Atlasでデータを確認してみます。
Cluster1-shard-0:PRIMARY> show dbs admin 0.000GB local 0.000GB main 0.000GB Cluster1-shard-0:PRIMARY> use main switched to db main Cluster1-shard-0:PRIMARY> show collections users Cluster1-shard-0:PRIMARY> db.users.find() { "_id" : ObjectId("58dddfc7e87a9d84c86068ed"), "userid" : 10000, "name" : "hoge1", "age" : 19 } { "_id" : ObjectId("58dddfc7e87a9d84c86068ee"), "userid" : 20000, "name" : "hoge2", "age" : 33 } { "_id" : ObjectId("58dddfc7e87a9d84c86068ef"), "userid" : 30000, "name" : "hoge3", "age" : 41 } { "_id" : ObjectId("58dddfc7e87a9d84c86068f0"), "userid" : 40000, "name" : "hoge4", "age" : 24 } { "_id" : ObjectId("58dddfc7e87a9d84c86068f1"), "userid" : 50000, "name" : "hoge5", "age" : 50 } { "_id" : ObjectId("58dddfc8e87a9d84c86068f2"), "userid" : 60000, "name" : "hoge6", "age" : 16 } Cluster1-shard-0:PRIMARY>
データが移行されています!
さらに継続歴レプリケーションを試すため、ソース側にデータをインサートしてみます。
s0-rs0:PRIMARY> db.users.insert({ userid:70000, name:"hoge7", age: 55 }); WriteResult({ "nInserted" : 1 }) s0-rs0:PRIMARY> s0-rs0:PRIMARY> db.users.find() { "_id" : ObjectId("58dddfc7e87a9d84c86068ed"), "userid" : 10000, "name" : "hoge1", "age" : 19 } { "_id" : ObjectId("58dddfc7e87a9d84c86068ee"), "userid" : 20000, "name" : "hoge2", "age" : 33 } { "_id" : ObjectId("58dddfc7e87a9d84c86068ef"), "userid" : 30000, "name" : "hoge3", "age" : 41 } { "_id" : ObjectId("58dddfc7e87a9d84c86068f0"), "userid" : 40000, "name" : "hoge4", "age" : 24 } { "_id" : ObjectId("58dddfc7e87a9d84c86068f1"), "userid" : 50000, "name" : "hoge5", "age" : 50 } { "_id" : ObjectId("58dddfc8e87a9d84c86068f2"), "userid" : 60000, "name" : "hoge6", "age" : 16 } { "_id" : ObjectId("58dde7c9c1a34a4d588ce97d"), "userid" : 70000, "name" : "hoge7", "age" : 55 } s0-rs0:PRIMARY>
ターゲット側で確認します。
Cluster1-shard-0:PRIMARY> use main switched to db main Cluster1-shard-0:PRIMARY> db.users.find() { "_id" : ObjectId("58dddfc7e87a9d84c86068ed"), "userid" : 10000, "name" : "hoge1", "age" : 19 } { "_id" : ObjectId("58dddfc7e87a9d84c86068ee"), "userid" : 20000, "name" : "hoge2", "age" : 33 } { "_id" : ObjectId("58dddfc7e87a9d84c86068ef"), "userid" : 30000, "name" : "hoge3", "age" : 41 } { "_id" : ObjectId("58dddfc7e87a9d84c86068f0"), "userid" : 40000, "name" : "hoge4", "age" : 24 } { "_id" : ObjectId("58dddfc7e87a9d84c86068f1"), "userid" : 50000, "name" : "hoge5", "age" : 50 } { "_id" : ObjectId("58dddfc8e87a9d84c86068f2"), "userid" : 60000, "name" : "hoge6", "age" : 16 } { "_id" : ObjectId("58dde7c9c1a34a4d588ce97d"), "userid" : 70000, "name" : "hoge7", "age" : 55 } Cluster1-shard-0:PRIMARY>
同期できました!
さいごに
いかがでしょうか。
mongomirrorを使うことで、簡単にAtlasに移行可能です。さらに、継続的レプリケーションも可能なので、稼働中のサービスも最小限の停止時間で同期が可能となります。