ちょっと話題の記事

[AWS] DocumentDB 詳細解説:MongoDB との違いを理解する

2019.02.09

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、菊池です。

個人的に念願のサービス、DocumentDBを触っています。

今回は、MongoDBとの機能・アーキテクチャ面での違いに注目します。すでにMongoDBを使っている環境をDocumentDBに移行するにあたって、どのような違いがあるのか、調べていきたいと思います。

  • APIの互換性
  • ストレージエンジンとクラスタアーキテクチャ
  • バックアップ

APIの互換性

まず、Amazon DocumentDBは、MongoDBのマネージドサービスではありません。MongoDBと互換性を持つようにAWSが開発したマネージド、ドキュメント指向データベースです。

Amazon DocumentDBは、現時点でMongoDB Version 3.4のAPIをベースにサポートしています。個々のAPI、オペレーション、データ型のサポートについては、ドキュメントにて公開されています。

一般的に使う主要な機能はサポートされていますが、既存アプリケーションの移行や、データ移行の際には影響の有無を確認しましょう。

ストレージエンジンとクラスタアーキテクチャ

MongoDBともっとも異なるのが、ストレージエンジンとクラスタアーキテクチャです。

MongoDBの場合、バージョン3.0以降に採用されたWiredTigerストレージエンジンが一般的であり、冗長化とRead負荷分散のためのレプリカセット、スケールアウトを実現するシャーディングといった機能があります。一方で、DocumentDBは独自のストレージエンジンを採用し、そのストレージエンジンに支えられたクラスタアーキテクチャをもちます。

MongoDBのクラスタ構成

MongoDBのレプリカセットクラスタでは、クラスタの各ノードがデータストレージを持ち、プライマリノードに書き込まれたデータが各セカンダリノードへ同期されます。レプリカセットクラスタでは、各ノードがお互いに通信しプライマノードを選出します。障害時のスプリットブレインを防止するため、クラスタ内のプライマリ選出に参加するノードは奇数にすることが必須であり、最小3台からの構成にすることが一般的です。

セカンダリノードは読み取り専用で利用することが可能なので、クラスタメンバーを増やすことでRead処理の負荷分散が可能です。

Write処理の負荷分散が必要なほどの大規模な利用環境においては、シャーディングによる負荷分散が可能です。

シャード構成では、前述のレプリカセットクラスタを複数ならべ、キー(シャードキー)による分散を行います。これにより、以下のようなケースにおけるスケールアウトが実現されます。

  • ファイルシステムの上限を超えるデータ領域が必要
  • プライマリノード1台では処理できないほどのWriteオペレーションが発生する

しかし、シャード構成に分散環境を管理するConfigサーバ、リクエストをルーティングするmongosが必要です。構成が複雑化し運用に対する負荷が非常に高くなりますので、まずはデータベースそのものを分割できないかを検討し、極力シャーディングを回避することをお勧めします。

DocumentDBのクラスタ構成

一方のDocumentDBのクラスタ構成です。

DocumentDBの可用性、信頼性は独自のクラスタボリュームにより実現されています。書き込まれたデータはクラスタノードの構成に依存せず、単一のクラスタボリュームに保存され、3つのアベイラビリティゾーン分散された6つのコピーが保持されます。

これはAmazon Auroraと同様の仕組みと考えられます。また、その利用状況に応じて64TBまで自動で拡張可能です。また、クラスタ内のインスタンスは1つのプライマリインスタンスと最大15のレプリカインスタンスの合計で最大16までの範囲で自由に選択できます。したがって、冗長化を考慮しても最小2台(プライマリ1+レプリカ1)から構成できます。

なお、DocumentDBではMongoDBのシャーディングのようなスケールアウト構成はサポートされません。そのため、最大64TBを超えるデータの格納が必要な場合や、1つのプライマリインスタンスで処理できない規模の書き込みオペレーションが発生する場合には、複数のクラスタにデータを分ける必要があります。ただ、前述の通りMongoDBでもシャーディングはスケールさせるための最終手段と捉えるべきなので、それが大きな制約とは考えるべきではないと思います。

フェイルオーバー動作

フェイルオーバーにおいては、MongoDB、DocumentDBともプライマリノードに異常が発生した場合にはいずれかのレプリカがプライマリに昇格する動作となります。複数のレプリカ(セカンダリ)が存在する場合、MongoDBの場合にはpriorityパラメータ、DocumentDBの場合には昇格階層パラメータによって優先度が設定可能です。

また、手動でのフェイルオーバーも可能です。異なるのは、フェールオーバー発生時のコネクションの扱いです。

MongoDBの場合、フェイルオーバーが発生しても、障害発生ノードやプライマリから降格するノード以外への影響は基本的にありません。リードレプリカへのReadオペレーションは影響なく継続することが可能です。

一方で、DocumentDBの場合、自動・手動に関わらずフェールオーバー発生時には、全てのクラスターノードでコネクションがリセットされます。そのため、わずかな時間ですがRead/Writeオペレーションにエラーが発生することに注意が必要です。

データの圧縮

スキーマレスなドキュメント指向データベースでは、全てのデータでキー項目を含めて保存します。そのため、厳格にスキーマが定義されるRDBに比べ、保持されるデータ量が大幅に大きくなる傾向があります。実際、データ圧縮のないMMAPv1ストレージエンジンの頃のMongoDBではデータ領域の肥大化が問題になることがありました。また、データサイズが大きいことは、ストレージへのIOも大きくなりますのでパフォーマンスの面でも不利です。

MongoDBではバージョン3.0以降で採用しているWiredTigerストレージエンジンで、デフォルトでデータ圧縮が有効です。データの内容や圧縮オプションにもよりますが、非圧縮(MMAPv1)に比べ1/20程度のサイズになっています。

一方のDocumentDBでは、ストレージに書き込むデータの圧縮の有無についてドキュメント上の記述は見つけられませんでした。実際にDocumentDBにデータを書き込み、利用ストレージ領域がどのようになるかを確認してみました。

1000Byteのオブジェクトを2000件、DocumentDBにインサートしました。その状態でDB、コレクションの状態を確認します。

rs0:PRIMARY> db.stats()
{
	"db" : "test1",
	"collections" : 1,
	"objects" : 2000,
	"storageSize" : 2375680,
	"indexes" : 1,
	"indexSize" : 98304,
	"fileSize" : 2473984,
	"ok" : 1
}
rs0:PRIMARY> db.COL.stats()
{
	"ns" : "test1.COL",
	"count" : 2000,
	"size" : 2036000,
	"avgObjSize" : 1018,
	"storageSize" : 2375680,
	"capped" : false,
	"nindexes" : 1,
	"totalIndexSize" : 98304,
	"indexSizes" : {
		"_id_" : 98304
	},
	"ok" : 1
}

データベース上からは、2375680Byteのストレージを利用していることがわかります。この状態でCloudWatchのメトリクス、VolumeBytesUsedを確認してみます。

書き込んだデータサイズに対し、利用されているデータ領域は17KByte程度とかなり小さくなっています。DocumentDBでも何らかのデータ圧縮が有効なようです。

バックアップ

MongoDBのバックアップでは、以下の3つの手法が一般的です。

  • MongoDBの管理ツール、CloudManger/OpsManagerによるバックアップ
  • 定期的なデータダンプの取得
  • インフラの機能を利用したバックアップ(データボリュームのスナップショットなど)

機能面でもっとも優れるのは公式が提供する管理ツールであるCloudManger/OpsManagerによるバックアップです。定期的なスナップショット取得、ポイントインタイムリカバリが可能です。しかし、どちらも有償サブスクリプションが必要であったり、機構が複雑なため運用面での負荷があります。

mongodumpを使ったデータダンプは簡単ですが、ダンプデータの退避先の確保やポイントインタイムリカバリには非対応といった課題があります。

インフラ機能を使うバックアップとは、AWSの場合にはEBSスナップショットの取得にあたります。こちらは手軽である一方で、リストア時のパフォーマンス(プレウォーミングが必要)やポイントインタイムリカバリには非対応といった課題があります。

実際のところ、MongoDBのバックアップ運用はどれも課題があるというのが実情と思います。一方で、バックアップ面ではDocumentDBに最大のアドバンテージがあるといえます。

DocumentDBの場合、RDSと同様に簡単な設定のみで最大35日分のバックアップが保存され、ポイントインタイムリカバリもサポートされます。また、任意のタイミングで手動スナップショットも可能です。リカバリも、対象のスナップショットを選択してクラスタを復元するだけです。正直、これだけでもMongoDBから移行する価値があると思います。

まとめ

以上、ドキュメントや実際に利用してわかった、MongoDBとDocumentDBの違いをまとめました。特にクラスタアーキテクチャとバックアップの仕組みは、設計や運用に与えるインパクトが大きいと思います。バックアップに関しては、さすがマネージドサービスとして提供しているだけあって、DocumentDBの優位性が高いと思います。

次は、既存のMongoDBからの移行について調べていきたいと思います。