MongoDB を備えた AEM

この記事は、MongoDB を備えた Adobe Experience Manager を正常にデプロイするために必要なタスクと考慮事項に関する知識を深めることを目的としています。

デプロイメントについて詳しくは、このドキュメントのデプロイとメンテナンスの節を参照してください。

AEM で MongoDB を使用する状況

MongoDB は通常、次のいずれかの条件を満たす AEM オーサーのデプロイメントをサポートする場合に使用します。

  • 1 日あたり 1,000 人を超える個別ユーザー
  • 100 人を超える同時ユーザー
  • 大量のページ編集
  • 大規模なロールアウトまたはアクティベーション

上述の条件が適用されるのはオーサーインスタンスのみです。すべて TarMK ベースであることが必要なパブリッシュインスタンスには適用されません。オーサーインスタンスでは、未認証のアクセスは許可されないので、ユーザー数は認証済みのユーザーを表します。

条件が満たされない場合は、可用性に対応するために、TarMK アクティブ/スタンバイデプロイメントをお勧めします。通常、MongoDB は、1 台のハードウェアで実現できる性能よりも高い拡張要件が求められる場合に検討してください。

メモ

オーサーインスタンスのサイジングと同時ユーザーの定義について詳しくは、ハードウェアのサイジングのガイドラインを参照してください。

AEM における MongoDB の最小デプロイメント

MongoDB での AEM の最小デプロイメントは次のとおりです。簡潔にするために、SSL ターミネーションおよび HTTP プロキシコンポーネントは一般化されています。これは、1 つのプライマリと 2 つのセカンダリを含む単一の MongoDB レプリカセットで構成されています。

chlimage_1-4

最小デプロイメントには、レプリカセットとして設定された 3 つの mongod インスタンスが必要です。1 つのインスタンスはプライマリとして選択され、その他のインスタンスはセカンダリとして選択されます。この選択は、mongod によって管理されます。各インスタンスにローカルディスクが接続されています。クラスターでこの負荷に対応するには、1 秒あたりの I/O 操作(IOPS)が 3,000 回を超える、12 MB/秒以上のスループットが推奨されます。

AEM オーサーは mongod インスタンスに接続されます。各 AEM オーサーは 3 つの mongod インスタンスすべてに接続します。書き込みはプライマリに送信され、読み取りはいずれのインスタンスからもおこなうことができます。トラフィックは、Dispatcher によって、負荷に基づいてアクティブな AEM オーサーインスタンスのいずれかに分散されます。OAK データストアは FileDataStore であり、MongoDB の監視は、デプロイメントの場所に応じて、MMS または MongoDB Ops Manager によって提供されます。オペレーティングシステムレベルの監視とログの監視は、Splunk や Ganglia のようなサードパーティソリューションによって提供されます。

このデプロイメントでは、実装が正常に機能するには、すべてのコンポーネントが必要です。いずれかのコンポーネントが不足していると、実装は機能しません。

オペレーティングシステム

AEM 6 でサポートされているオペレーティングシステムのリストについては、技術要件のページを参照してください。

環境

仮想化環境をサポートするには、プロジェクトを実行する様々な技術チームが適切にコミュニケーションを取る必要があります。これには、AEM を実行するチーム、オペレーティングシステムを所有するチームおよび仮想化インフラストラクチャを管理するチームが含まれます。

MongoDB インスタンスの I/O 処理能力については特殊な要件があり、この要件の管理は仮想化環境を管理するチームがおこなう必要があります。Amazon Web Services などのクラウドデプロイメントをプロジェクトで使用する場合、MongoDB インスタンスをサポートするための十分な I/O 処理能力と整合性が得られるようにインスタンスをプロビジョニングする必要があります。そうしないと、MongoDB プロセスと Oak リポジトリの動作が、信頼性が低く不安定なものになります。

仮想化環境では、VMWare のリソース割り当てポリシーによって MongoDB のストレージエンジンの機能が損なわれることがないように、MongoDB で特殊な I/O および VM の設定が必要になります。適切な実装では、個々のチーム間の障壁がなくなり、必要なパフォーマンスを実現するためにすべてのチームが連携して作業します。

ハードウェアに関する考慮事項

ストレージ

水平方向のスケーリングを早い段階でおこなうことなく、読み書きのスループットが最適なパフォーマンスになるようにするには、通常、SSD ストレージまたは SSD 相当のパフォーマンスを提供するストレージが MongoDB で必要となります。

RAM

MMAP ストレージエンジンを使用する MongoDB バージョン 2.6 および 3.0 では、データベースとそのインデックスの作業セットが RAM に収まる必要があります。

十分な RAM がないとパフォーマンスが大幅に低下します。作業セットとデータベースのサイズは、アプリケーションに大きく依存します。ある程度の概算をおこなうことはできますが、必要な RAM の容量を特定するための最も信頼できる方法は、AEM アプリケーションを構築して負荷テストを実施することです。

負荷テストを実施する場合は、データベースの合計サイズに対する作業セットの比率を次のように想定することができます。

  • SSD ストレージの場合は 1:10
  • ハードディスクストレージの場合は 1:3

つまり、SSD デプロイメントの場合、2 TB のデータベースには 200 GB の RAM が必要です。

MongoDB 3.0 の WiredTiger ストレージエンジンにも同じ制限が適用されますが、WiredTiger では MMAP ストレージエンジンと同様の方法でメモリマッピングを使用しないので、作業セット、RAM およびページフォールトの間の相関関係はそれほど強くありません。

メモ

MongoDB 3.0 を使用する AEM 6.1 のデプロイメントには、WiredTiger ストレージエンジンを使用することをお勧めします。

データストア

MongoDB の作業セットに関する制限により、データストアを MongoDB から独立して保持することを強くお勧めします。ほとんどの環境では、すべての AEM インスタンスに対して使用可能な NAS を使用する FileDataStore を使用してください。Amazon Web Services を使用する場合は、S3 DataStore もあります。何らかの理由でデータストアを MongoDB 内に保持する場合は、データストアのサイズをデータベースの合計サイズに加算し、作業セットの計算を適切に調整する必要があります。これは、ページフォールトを発生させずにパフォーマンスを維持するには、はるかに多くの RAM をプロビジョニングすることを意味する場合があります。

モニタリング

プロジェクトを正常に実装するには監視が不可欠です。十分な知識があれば、監視なしでも MongoDB 上で AEM を実行することは可能ですが、その知識を持っているのは通常、デプロイメントの各セクションを専門とするエンジニアです。

これは一般に、Apache Oak コアに取り組む R&D エンジニアや MongoDB スペシャリストなどです。

すべてのレベルにおいて監視がない場合、問題を診断するためにコードベースの詳細な知識が必要になります。監視が実施されて、主要な統計に関する適切なガイダンスが提供されれば、実装チームは異常に対して的確に対応できます。

コマンドラインツールを使用してクラスターの動作のクイックスナップショットを取得することもできますが、多数のホストに対してリアルタイムでこれをおこなうのはほぼ不可能です。コマンドラインツールで数分間を超える履歴情報が提供されることはほとんどなく、様々なタイプの指標を相関させることもできません。mongod のバックグラウンド同期が短期間遅くなると、見かけ上は接続されていない仮想マシンからの共有ストレージリソースに対する I/O の待機や過剰な書き込みレベルの相関関係を見つけるために手動による多大な労力が必要になります。

MongoDB Cloud Manager

MongoDB Cloud Manager は、MongoDB インスタンスを監視および管理できる、MongoDB で提供される無料のサービスです。これにより、MongoDB クラスターのパフォーマンスとヘルスをリアルタイムで把握できます。また、インスタンスが Cloud Manager 監視サーバーにアクセスできる場合は、クラウドでホストされているインスタンスとプライベートにホストされているインスタンスの両方を管理できます。

このサービスを使用するには、監視サーバーに接続する MongoDB インスタンスにエージェントがインストールされている必要があります。エージェントには次の 3 つのレベルがあります。

  • MongoDB サーバー上のすべてのものを完全に自動化できる自動化エージェント
  • mongod インスタンスを監視できる監視エージェント
  • スケジュールされたデータバックアップを実行できるバックアップエージェント

Cloud Manager を使用して MongoDB クラスターのメンテナンスを自動化すると、定期的なタスクの多くが容易になりますが、これは必須ではありません。また、バックアップに Cloud Manager を使用することも必須ではありません。ただし、監視をおこなうために Cloud Manager を選択した場合、監視は必須です。

MongoDB Cloud Manager について詳しくは、MongoDB のドキュメントを参照してください。

MongoDB Ops Manager

MongoDB Ops Manager は、MongoDB Cloud Manager と同じソフトウェアです。登録すると、Ops Manager をダウンロードして、プライベートデータセンターまたは他のラップトップマシンやデスクトップマシンにローカルにインストールできます。このソフトウェアは、ローカルの MongoDB データベースを使用してデータを格納し、Cloud Manager とまったく同様に管理対象サーバーと通信します。セキュリティポリシーで監視エージェントを禁止している場合は、MongoDB Ops Manager を使用してください。

オペレーティングシステムの監視

AEM MongoDB クラスターを実行するには、オペレーティングシステムレベルの監視が必要です。

そのようなシステムの良い例として Ganglia があります。Ganglia では、対象範囲の概要情報が提供され、CPU、負荷平均、空きディスク領域のようなヘルスに関する基本的な指標にとどまらず、必要な情報の詳細を表示できます。問題を診断するには、エントロピープールレベル、CPU I/O 待機、FIN_WAIT2 状態のソケットなど、下位レベルの情報が必要です。

ログの集約

複数のサーバーで構成されるクラスターの場合、実稼動システムにはログの一元的な集約が必要となります。Splunk のようなソフトウェアではログの集約がサポートされており、チームは、ログを手動で収集しなくても、アプリケーションの動作のパターンを分析できます。

チェックリスト

ここでは、プロジェクトを実装する前に、AEM と MongoDB のデプロイメントを適切に設定するために実行する必要がある様々な手順について説明します。

ネットワーク

  1. まず、すべてのホストに DNS エントリがあることを確認します。
  2. ルーティング可能な他のすべてのホストから、すべてのホストがそれぞれの DNS エントリによって解決できる必要があります。
  3. MongoDB ホストはすべて、同じクラスター内の他のすべての MongoDB ホストからルーティング可能です。
  4. MongoDB ホストは、MongoDB Cloud Manager およびその他の監視サーバーにパケットをルーティングできます。
  5. AEM サーバーは、すべての MongoDB サーバーにパケットをルーティングできます。
  6. AEM サーバーと MongoDB サーバーの間のパケットの遅延は 2 ミリ秒未満であり、パケットの損失がなく、標準的な配信は 1 ミリ秒以下です。
  7. AEM サーバーと MongoDB サーバーの間のホップは 2 つまでです。
  8. 2 つの MongoDB サーバー間のホップは 2 つまでです。
  9. 任意のコアサーバー(MongoDB、AEM または任意の組み合わせ)間のルーターは OSI レベル 3 以下です。
  10. VLAN トランキングまたは何らかの形のネットワークトンネリングを使用している場合、パケット遅延チェックに適合している必要があります。

AEM の設定

ノードストアの設定

MongoMK を選択して AEM を使用するように AEM インスタンスを設定する必要があります。AEM における MongoMK 実装の基盤はドキュメントノードストアです。

ノードストアを設定する方法について詳しくは、AEM でのノードストアとデータストアの設定を参照してください。

次に、MongoDB の最小デプロイメントにおけるドキュメントノードストアの設定の例を示します。

# org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService.config
#MongoDB server details
mongodburi=mongodb://aem:aempassword@mongodbserver1.customer.com:27000,mongodbserver2.customer.com:27000

#Name of MongoDB database to use
db=aem

#Store binaries in custom BlobStore e.g. FileDataStore
customBlobStore=true

cache=2048
blobCacheSize=1024

ここで、

  • mongodburi
    これは、AEM が接続する必要がある MongoDB サーバーです。接続は、デフォルトレプリカセットの既知のメンバーすべてに対して確立されます。MongoDB Cloud Manager を使用する場合は、サーバーセキュリティが有効になります。そのため、適切なユーザー名とパスワードが接続文字列に含まれている必要があります。エンタープライズ以外のバージョンの MongoDB では、ユーザー名およびパスワード認証のみがサポートされます。接続文字列の構文について詳しくは、こちらのドキュメントを参照してください。

  • dbデータベースの名前。AEM のデフォルトは
    aem-author です。

  • customBlobStore
    デプロイメントでバイナリがデータベースに格納される場合、バイナリは作業セットの一部になります。そのため、バイナリを MongoDB 内に格納せず、できれば、NAS 上の
    NAS 上の FileSystem データストア。

  • cache
    キャッシュサイズ(メガバイト単位)です。これは
    DocumentNodeStore で使用される様々なキャッシュに配分されます。デフォルトは 256MB です。ただし、キャッシュが大きいほうが Oak の読み取りパフォーマンスは向上します。

  • blobCacheSize
    頻繁に使用される Blob は、データストアから再取得しなくて済むように、AEM にキャッシュできます。これは、Blob を MongoDB データベースに格納する場合は特に、パフォーマンスへの影響が大きくなります。オペレーティングシステムレベルのディスクキャッシュは、ファイルシステムベースのすべてのデータストアに効果的です。

データストアの設定

データストアは、しきい値よりも大きいサイズのファイルを格納するために使用されます。そのしきい値以下のファイルは、ドキュメントノードストア内にプロパティとして格納されます。MongoBlobStore を使用する場合、Blob を格納するための専用のコレクションが MongoDB に作成されます。このコレクションは mongod インスタンスの作業セットに含まれ、パフォーマンスの問題を回避するには、より大きな RAM が mongod に必要になります。そのため、実稼動デプロイメントでは MongoBlobStore を使用せず、すべての AEM インスタンス間で共有される、NAS によって提供される FileDataStore を使用する設定をお勧めします。ファイルの管理にはオペレーティングシステムレベルのキャッシュが効率的なので、ディスク上のファイルの最小サイズをディスクのブロックサイズに近い値に設定して、ファイルシステムが効率的に使用され、mongod インスタンスの作業セットに多数の小さいドキュメントが過剰に含まれないようにします。

次に、MongoDB を使用した AEM の最小デプロイメントにおける一般的なデータストアの設定を示します。

# org.apache.jackrabbit.oak.plugins.blob.datastore.FileDataStore.config
# The minimum size of an object that should be stored in this data store.
minRecordLength=4096
path=/datastore
maxCachedBinarySize=4096
cacheSizeInMB=128

ここで、

  • minRecordLength
    サイズ(バイト単位)。このサイズ以下のバイナリは、ドキュメントノードストアに格納されます。Blob の ID を格納するのではなく、バイナリの内容が格納されます。このサイズを超えるバイナリについては、バイナリの ID がドキュメントのプロパティとしてノードのコレクションに格納され、バイナリの本文はディスク上の
    ディスク上の FileDataStore に。一般的なファイルシステムのブロックサイズは 4,096 バイトです。

  • path
    データストアのルートのパスです。MongoMK デプロイメントの場合、これはすべての AEM インスタンスで使用可能な共有ファイルシステムである必要があります。通常は、ネットワーク接続ストレージ(NAS)サーバーを使用します。Amazon Web Services などのクラウドデプロイメントの場合、
    S3DataFileStore も利用できます。

  • cacheSizeInMB
    バイナリキャッシュの合計サイズ(メガバイト単位)です。これは、以下のものより小さいバイナリをキャッシュするために使用されます:
    maxCacheBinarySize の設定値。

  • maxCachedBinarySize
    バイナリキャッシュにキャッシュされるバイナリの最大サイズ(バイト単位)です。ファイルシステムベースのデータストアを使用する場合、バイナリはオペレーティングシステムによって既にキャッシュされているので、データストアのキャッシュに大きい値を使用することはお勧めしません。

クエリヒントの無効化

すべてのクエリと共に送信されるクエリヒントを無効にすることをお勧めします。

-Doak.mongo.disableIndexHint=true

そのためには、AEM の起動時に上述のプロパティを追加します。これにより、MongoDB では、内部統計に基づいて最も適切なインデックスで計算がおこなわれます。

クエリヒントが無効でない場合は、インデックスのパフォーマンスをチューニングしても AEM のパフォーマンスには影響しません。

MongoMK の永続キャッシュの有効化

I/O の読み取りパフォーマンスを高くして環境での処理速度を最大化するには、MongoDB デプロイメントで永続キャッシュ設定を有効にすることをお勧めします。詳しくは、Jackrabbit Oak のドキュメントを参照してください。

MongoDB オペレーティングシステムの最適化

オペレーティングシステムのサポート

MongoDB 2.6 では、メモリマップストレージエンジンを使用します。このストレージエンジンは、RAM とディスクに関するオペレーティングシステムレベルの管理でのいくつかの特性の影響を受けます。MongoDB インスタンスのクエリと読み取りのパフォーマンスを向上させるには、ページフォールトと呼ばれることもある、低速な I/O 操作を回避または排除する必要があります。これらは、特に mongod プロセスに適用されるページフォールトです。オペレーティングシステムレベルのページフォールトと混同しないでください。

高速な操作のためには、既に RAM に存在しているデータにのみ MongoDB データベースがアクセスする必要があります。アクセスする必要があるデータは、インデックスとデータで構成されています。インデックスとデータのこのコレクションは、作業セットと呼ばれます。使用可能な RAM よりも作業セットが大きい場合、MongoDB はディスクからそのデータをページインする必要があり(これにより、I/O コストが発生します)、既にメモリ内にある他のデータが消去されます。この消去が原因となってデータがディスクから再度読み込まれると、ページフォールトが増えてパフォーマンスが低下します。作業セットが動的で変動する場合は、操作をサポートするために、さらに多くのページフォールトが発生します。

MongoDB は、Linux の幅広いフレーバー、Windows、Mac OS を含む、数多くのオペレーティングシステムで動作します。詳しくは、https://docs.mongodb.com/manual/installation/#supported-platforms を参照してください。MongoDB には、選択したオペレーティングシステムによって、異なるオペレーティングシステムレベルの推奨事項があります。これらは https://docs.mongodb.com/manual/administration/production-checklist-operations/#operating-system-configuration に掲載されていますが、ここでも簡単にまとめておきます。

Linux

  • Transparent Huge Page(THP)および defrag を無効にします。詳しくは、Transparent Huge Page(THP)の設定についての説明を参照してください。

  • 使用状況に応じてデータベースファイルを格納するデバイスの readahead の設定を調整します。

    • MMAPv1 ストレージエンジンでは、作業セットが利用可能な RAM よりも大きく、ドキュメントのアクセスパターンがランダムな場合、readahead を 32 または 16 に下げることを検討します。様々な設定を試し、使用するメモリの量を最大化でき、ページフォールトの回数を低減できる最適な値を見つけます。
    • WiredTiger ストレージエンジンでは、ストレージメディアタイプ(回転式のディスク、SSD など)にかかわらず、readahead を 0 に設定します。一般的に、readahead の値を高くすることで、測定可能、再現可能、かつ信頼性のあるメリットがあることをテストで確認できた場合を除き、この推奨 readahead 設定を使用します。MongoDB のプロフェッショナルサポートで、0 以外の readahead 設定を使用する場合のアドバイスとガイダンスを受けることができます。
  • 仮想環境で RHEL 7/CentOS 7 を実行している場合は、Tuned ツールを無効にします。

  • 仮想環境で RHEL 7/CentOS 7 を実行すると、Tuned ツールによって、パフォーマンスのスループットから得られたパフォーマンスプロファイルが自動的に呼び出され、これにより readahead 設定が自動的に 4 MB に設定されます。この設定は、パフォーマンスに悪影響を与えます。

  • SSD ドライブでは、noop または deadline ディスクスケジューラーを使用します。

  • ゲスト VM での仮想化ドライブでは、noop ディスクスケジューラーを使用します。

  • NUMA を無効にするか、vm.zone_reclaim_mode を 0 に設定し、ノードインタリーブを指定して mongod インスタンスを実行します。詳しくは、MongoDB and NUMA Hardware(MongoDB と NUMA ハードウェア)を参照してください。

  • 使用状況に応じてハードウェアの ulimit 値を調整します。同じユーザーで複数の mongod または mongos インスタンスを実行する場合、適宜 ulimit 値を拡張します。詳しくは、UNIX ulimit Settings(UNIX の ulimit の設定)を参照してください。

  • dbPath マウントポイントに noatime を使用します。

  • デプロイメントにとって十分なファイルハンドル数(fs.file-max)、カーネルの pid の制限(kernel.pid_max)およびプロセスごとの最大スレッド数(kernel.threads-max)の設定にします。大規模なシステムでは、まず以下の設定から試すことをお勧めします。

    • fs.file-max の値:98000
    • kernel.pid_max の値:64000
    • andkernel.threads-max の値:64000
  • システムに、スワップ領域が設定されていることを確認します。適切なサイジングについて詳しくは、オペレーティングシステムのドキュメントを参照してください。

  • システムのデフォルトの TCP キープアライブが正しく設定されていることを確認します。レプリカセットおよびシャードクラスターでは、300 の値を設定すると、多くの場合パフォーマンスが良くなります。詳しくは、Frequently Asked Questions(よくある質問)の Does TCP keepalive time affect MongoDB Deployments? (TCP キープアライブ時間は MongoDB のデプロイメントに影響がありますか)を参照してください。

Windows

  • NTFS の「最終アクセス時刻」の更新を無効にすることを検討します。これは、Unix 系システムで atime を無効にすることと似ています。

WiredTiger

MongoDB 3.2 以降、MongoDB のデフォルトのストレージエンジンは WiredTiger ストレージエンジンとなっています。このエンジンは、数多くの堅牢で拡張性のある機能を備えており、あらゆる一般的なデータベースワークロードに適したものとなっています。以下では、これらの機能について説明します。

ドキュメントレベルの同時実行性

WiredTiger では、書き込み操作に対して、ドキュメントレベルでの同時実行制御を使用しています。そのため、複数のクライアントが特定のコレクションの異なるドキュメントを同時に変更することができます。

ほとんどの読み取りおよび書き込み操作で、WiredTiger は楽観的同時実行制御を使用します。WiredTiger は、グローバル、データベースおよびコレクションのレベルで、インテントロックのみを使用します。ストレージエンジンが 2 つの操作の間で競合を検出すると、一方の操作で書き込みの競合が生じ、MongoDB は透過的にその操作を再試行します。一部のグローバルな操作(通常は複数のデータベースに関係する短時間の操作)では、引き続きグローバルな「インスタンス全体の」ロックが必要となります。

コレクションの削除などのその他の一部の操作では、引き続き排他的データベースロックが必要です。

スナップショットとチェックポイント

WiredTiger はマルチバージョン同時実行制御(MVCC)を使用しています。WiredTiger は、操作の開始時にトランザクションに対してデータの特定の時点のスナップショットを提供します。スナップショットは、インメモリデータの整合性のあるビューです。

WiredTiger は、ディスクに書き込む際、すべてのデータファイルでの整合性が保たれるように、スナップショットのすべてのデータをディスクに書き込みます。この永続化されたデータは、データファイル内のチェックポイントとして機能します。チェックポイントでは、最後のチェックポイントに至るまでデータファイルの整合性が保たれることが保証されます。つまり、チェックポイントは復元ポイントとして機能します。

MongoDB では、60 秒間隔または 2 GB のジャーナルデータごとにチェックポイントを作成(スナップショットデータをディスクに書き込み)するよう WiredTiger が設定されます。

新しいチェックポイントの書き込み中は、以前のチェックポイントが引き続き有効となります。そのため、新しいチェックポイントの書き込み中に MongoDB が終了したり、エラーが発生した場合でも、再起動時には最後の有効なチェックポイントから MongoDB の復元が可能です。

WiredTiger のメタデータテーブルがアトミックに更新され、新しいチェックポイントを参照するようになると、新しいチェックポイントにアクセスできるようになるとともに、新しいチェックポイントが永続化されます。新しいチェックポイントにアクセス可能になると、WiredTiger は古いチェックポイントからページを解放します。

WiredTiger を使用すると、ジャーナル処理をおこなわなくても MongoDB は最後のチェックポイントから復元できます。ただし、最後のチェックポイントが作成された後の変更を復元するには、ジャーナル処理を有効にして実行します。

ジャーナル

WiredTiger では、トランザクションログの先行書き込みとチェックポイントを使用して、データの永続性を確保しています。

WiredTiger ジャーナルにより、チェックポイント間におこなわれたすべてのデータ変更が永続化されます。チェックポイント間に MongoDB が終了すると、最後のチェックポイント以降に変更されたすべてのデータがジャーナルを使用して再現されます。MongoDB がジャーナルデータをディスクに書き込む頻度について詳しくは、Journaling Process(ジャーナル処理プロセス)を参照してください。

WiredTiger のジャーナルは、snappy 圧縮ライブラリを使用して圧縮されます。別の圧縮アルゴリズムを指定する場合、または圧縮しない場合は、storage.wiredTiger.engineConfig.journalCompressor 設定を使用します。

詳しくは、ジャーナル処理と WiredTigerを参照してください。

メモ

WiredTiger の最小ログレコードサイズは 128 バイトです。ログレコードが 128 バイト以下の場合、WiredTiger はそのレコードを圧縮しません。

storage.journal.enabled を false に設定すると、ジャーナル処理を無効にすることができ、ジャーナルを維持するためのオーバーヘッドを削減できます。

スタンドアロンインスタンスでは、ジャーナルを使用しないと、チェックポイント間で MongoDB が予期せず終了したときに一部のデータ変更が失われることになります。レプリカセットのメンバーでは、レプリケーションプロセスで十分な永続性が保証される可能性があります。

圧縮

WiredTiger を使用する場合、MongoDB では、すべてのコレクションおよびインデックスで圧縮がサポートされます。圧縮を使用することで、必要なストレージ容量を最小限に抑えることができますが、その分 CPU の負荷が高くなります。

デフォルトで、WiredTiger は、すべてのコレクションで snappy 圧縮ライブラリを使用したブロック圧縮を、すべてのインデックスでプレフィックス圧縮を使用します。

コレクションでは、zlib によるブロック圧縮も利用できます。別の圧縮アルゴリズムを指定する場合、または圧縮しない場合は、storage.wiredTiger.collectionConfig.blockCompressor 設定を使用します。

インデックスでプレフィックス圧縮を無効にするには、storage.wiredTiger.indexConfig.prefixCompression設定を使用します。

圧縮設定は、コレクションおよびインデックスの作成時に、コレクションごと、およびインデックスごとに設定することもできます。Specify Storage Engine Options(ストレージエンジンのオプションの指定)および db.collection.createIndex() の storageEngine オプションを参照してください。

ほとんどのワークロードでは、デフォルトの圧縮設定を使用すると、ストレージ利用の効率性と、処理速度の要件のバランスをとることができます。

デフォルトで、WiredTiger のジャーナルも圧縮されます。ジャーナルの圧縮について詳しくは、Journal(ジャーナル)を参照してください。

メモリの使用

WiredTiger を使用する場合、MongoDB は WiredTiger の内部キャッシュとファイルシステムキャッシュの両方を利用します。

WiredTiger の内部キャッシュは、3.4 以降、デフォルトで、以下のいずれか大きい方を使用します。

  • RAM の 50%から 1 GB を減算したサイズ
  • 256 MB

WiredTiger は、デフォルトで、すべてのコレクションには Snappy ブロック圧縮を、すべてのインデックスにはプレフィックス圧縮を使用します。圧縮のデフォルトはグローバルレベルで設定できます。コレクションおよびインデックスの作成時に、コレクションごと、およびインデックスごとに設定することもできます。

WiredTiger の内部キャッシュのデータでは、ディスク上の形式とは異なるデータ表現が使用されます。

  • ファイルシステムキャッシュのデータはディスク上の形式と同じで、データファイルの圧縮によるメリットも同等です。ファイルシステムキャッシュは、オペレーティングシステムがディスク I/O を低減するために使用します。

WiredTiger の内部キャッシュに読み込まれるインデックスでは、ディスク上の形式とは異なるデータ表現が使用されますが、インデックスのプレフィックス圧縮を使用して RAM の使用量を削減できます。

インデックスのプレフィックス圧縮は、インデックスが作成されたフィールドの共通のプレフィックスの重複を除去します。

WiredTiger の内部キャッシュのコレクションデータは圧縮されておらず、ディスク上の形式とは異なる表現が使用されます。ブロック圧縮をおこなうとディスクストレージ使用容量を大幅に削減できますが、サーバーがデータを操作する際にデータの展開が必要になります。

ファイルシステムキャッシュでは、MongoDB は、WiredTiger のキャッシュや他のプロセスで使用されていないすべての空きメモリを自動的に使用します。

WiredTiger の内部キャッシュのサイズを調整するには、storage.wiredTiger.engineConfig.cacheSizeGB および –wiredTigerCacheSizeGB を参照してください。WiredTiger の内部キャッシュのサイズは、デフォルト値よりも大きくしないでください。

NUMA

Non Uniform Memory Access(NUMA)を使用すると、プロセッサーコアにメモリをマップする方法をカーネルで管理できます。これにより、コアのメモリアクセスを高速化し、必要なデータに確実にアクセスできるようにする試みがおこなわれますが、NUMA は MMAP に干渉し、読み取りを予測できないのでさらに遅延が発生します。この理由から、NUMA に対応しているすべてのオペレーティングシステムの mongod プロセスでこの機能を無効にする必要があります。

基本的に、NUMA アーキテクチャでは、メモリは複数の CPU に接続され、複数の CPU はバスに接続されます。SMP または UMA アーキテクチャでは、メモリはバスに接続され、複数の CPU によって共有されます。スレッドが NUMA CPU のメモリを割り当てる際には、ポリシーに従って割り当てられます。デフォルトでは、スレッドのローカル CPU に接続されたメモリが割り当てられます。空きがない場合は、よりコストの高い空いている CPU のメモリが使用されます。一度割り当てられたメモリは CPU 間で移動しません。割り当ては、親スレッド(つまり、プロセスを開始したスレッド)から継承されたポリシーによって実行されます。

マシンをマルチコアの均一なメモリアーキテクチャと見なす多くのデータベースでは、これにより、最初の CPU が最初にいっぱいになり、次の CPU がその後にいっぱいになります。中核となるスレッドがメモリバッファを割り当てる場合は特にそうなります。これを解決するには、mongodプロセスを開始するために使用されるメインスレッドの NUMA ポリシーを変更します。

そのためには、次のコマンドを実行します。

numactl --interleaved=all <mongod> -f config

このポリシーでは、すべての CPU ノードでラウンドロビン方式でメモリが割り当てられるので、すべてのノードで配分が均等になります。CPU ハードウェアが複数あるシステムの場合のように、メモリに対する最も高速なアクセスが生成されるわけではありません。メモリ操作の約半分は速度が低下し、バスを経由しておこなわれますが、mongod は NUMA を目的として最適な方法で記述されているわけではないので、これは合理的な妥協策です。

NUMA に関する問題

/etc/init.d フォルダー以外の場所から mongod プロセスが開始された場合、適切な NUMA ポリシーで開始されない可能性があります。デフォルトポリシーによっては、問題が発生することがあります。これは、MongoDB 用の様々な Linux パッケージマネージャーインストーラーが、/etc/init.d に設定ファイルとともにサービスをインストールし、それにより上記の手順が実行されるからです。アーカイブ(.tar.gz)から直接 MongoDB をインストールして実行する場合は、mongod を numactl プロセスで手動で実行する必要があります。

メモ

使用可能な NUMA ポリシーについて詳しくは、numactl のドキュメントを参照してください。

MongoDB プロセスの動作は、個々の割り当てポリシーによって異なります。


  • -membind=<nodes>
    リストされているノードのみで割り当てをおこないます。mongod では、リストされているノードのメモリが割り当てられず、使用可能なメモリの一部が使用されない可能性があります。

  • -cpunodebind=<nodes>
    ノードのみで実行します。mongod は、指定されたノードのみで実行され、それらのノードで使用可能なメモリのみを使用します。

  • -physcpubind=<nodes>
    リストされている CPU(コア)のみで実行します。mongod は、リストされている CPU のみで実行され、それらの CPU で使用可能なメモリのみを使用します。

  • --localalloc
    常に現在のノードのメモリを割り当てますが、スレッドを実行しているすべてのノードを使用します。1 つのスレッドで割り当てが実行されている場合は、その CPU で使用可能なメモリのみが使用されます。

  • --preferred=<node>
    指定されたノードへの割り当てを優先しますが、優先されるノードがいっぱいである場合は他のノードにフォールバックします。ノードを定義するための相対注釈を使用できます。また、スレッドはすべてのノードで実行されます。

一部のポリシーでは、mongod プロセスに割り当てられるメモリが、使用可能なすべての RAM よりも少ない場合があります。MySQL とは異なり、MongoDB はオペレーティングシステムレベルのページングを積極的に回避します。その結果、使用可能であると思われるメモリよりも少ない量のメモリが mongod プロセスに割り当てられることがあります。

スワッピング

データベースはその性質上、大量のメモリを使用するので、オペレーティングシステムレベルのスワッピングを無効にする必要があります。MongoDB プロセスは、スワッピングしないように設計されています。

リモートファイルシステム

NFS などのリモートファイルシステムでは、非常に多くの遅延が発生します。そのため、MongoDB の内部データファイル(mongod プロセスデータベースファイル)にはお勧めしません。Oak Blob の格納に必要な共有ファイルシステム(FileDataStore)の場合は、NFS が推奨されます。

先読み

ランダム読み取りを使用してページがページインされる際に、不要なブロックがディスクから読み取られ、I/O 帯域幅が不必要に使用されることがないように、先読みを調整する必要があります。

Linux に関する要件

カーネルの最小バージョン

  • ext4 ファイルシステムの場合 2.6.23

  • xfs ファイルシステムの場合 2.6.25

atime の無効化

データベースを格納するディスクについては atime を無効にすることをお勧めします。

NOOP ディスクスケジューラーの設定

手順は次のとおりです。

まず、現在設定されている I/O スケジューラーを確認します。そのためには、次のコマンドを実行します。

cat /sys/block/sdg/queue/scheduler

応答が noop である場合、さらに操作をおこなう必要はありません。

設定されている I/O スケジューラーが NOOP でない場合は、次のコマンドを実行して変更できます。

echo noop > /sys/block/sdg/queue/scheduler

先読み値の調整

MongoDB データベースが実行されるディスクでは、値を 32 にすることをお勧めします。これは 16 キロバイトに相当します。これを設定するには、次のコマンドを実行します。

sudo blockdev --setra <value> <device>

NTP の有効化

MongoDB データベースをホストしているマシンに NTP がインストールされ、実行されていることを確認します。例えば、CentOS マシンで yum パッケージマネージャーを使用してインストールできます。

sudo yum install ntp

NTP デーモンがインストールされ、正常に起動したら、ドリフトファイルでサーバーの時刻のずれを確認できます。

Transparent Huge Pages の無効化

Red Hat Linux では、Transparent Huge Pages(THP)と呼ばれるメモリ管理アルゴリズムが使用されます。このオペレーティングシステムをデータベースワークロードに使用している場合は、これを無効にすることをお勧めします。

無効にするには、次の手順に従います。

  1. /etc/grub.conf ファイルを任意のテキストエディターで開きます。

  2. grub.conf ファイルに次の行を追加します。

    transparent_hugepage=never
    
  3. 最後に、次のコマンドを実行して、設定が有効になっているかどうかを確認します。

    cat /sys/kernel/mm/redhat_transparent_hugepage/enabled
    

    THP が無効になっている場合、このコマンドの出力は次のようになります。

    always madvise [never]
    
メモ

Transparent Huge Pages について詳しくは、こちらの記事を参照してください。

NUMA の無効化

NUMA が有効なほとんどのインストール環境では、NUMA が /etc/init.d フォルダーからサービスとして実行される場合、MongoDB デーモンによって自動的に無効化されます。

そうでない場合は、各プロセスレベルで NUMA を無効にすることができます。無効にするには、次のコマンドを実行します。

numactl --interleave=all <path_to_process>

<path_to_process> は、mongod プロセスへのパスです。

続いて、次のコマンドを実行してゾーンの再利用を無効にします。

echo 0 > /proc/sys/vm/zone_reclaim_mode

mongod プロセスの ulimit 設定の微調整

Linux では、ulimit コマンドによるリソースの割り当てを設定で制御できます。これは、ユーザーごとに行うことも、プロセスごとに行うこともできます。

MongoDB における ulimit の推奨設定に従って、mongod プロセスの ulimit を設定することをお勧めします。

MongoDB の I/O パフォーマンスのテスト

MongoDB には、I/O パフォーマンスのテストを目的とした mongoperf というツールが用意されています。このツールを使用して、インフラストラクチャを構成しているすべての MongoDB インスタンスのパフォーマンスをテストすることをお勧めします。

mongoperf の使用方法について詳しくは、MongoDB のドキュメントを参照してください。

メモ

mongoperf は、MongoDB が実行されているプラットフォームにおける MongoDB のパフォーマンスの指標となるように設計されています。これによって、実稼動システムでのパフォーマンスを保証するものとして結果を捉えないでください。

より正確なパフォーマンス結果を得るには、fio Linux ツールを使用して補完テストを実行できます。

デプロイメントを構成している仮想マシンでの読み取りパフォーマンスのテスト

ツールをインストールしたら、テストを実行するために MongoDB データベースディレクトリに切り替えます。続いて、次の設定で mongoperf を実行して、最初のテストを開始します。

echo "{nThreads:32,fileSizeMB:1000,r:true}" | mongoperf

すべての MongoDB インスタンスで、最大 1 秒あたり 2 ギガバイト(2 GB/秒)および 500,000 IOPS を 32 スレッドで実行しているのが望ましい結果です。

2 回目のテストを実行します。今回は mmf:true パラメーターを設定して、メモリマップファイルを使用します。

echo "{nThreads:32,fileSizeMB:1000,r:true,mmf:true}" | mongoperf

2 回目のテストの結果は最初のテストよりもかなり高くなり、メモリ転送のパフォーマンスが良くなったことを示しています。

メモ

テストを実施するときは、オペレーティングシステムのモニタリングシステムで対象の仮想マシンの I/O 使用率の状況を確認してください。I/O 読み取りが 100 パーセントに満たない値を示している場合は、仮想マシンに問題がある可能性があります。

プライマリ MongoDB インスタンスの書き込みパフォーマンステスト

次に、同じ設定で MongoDB データベースディレクトリから mongoperf を実行して、プライマリ MongoDB インスタンスの I/O 書き込みパフォーマンスを確認します。

echo "{nThreads:32,fileSizeMB:1000,w:true}" | mongoperf

この出力が 1 秒あたり 12 メガバイトで、約 3,000 IOPS に達していて、スレッド数による変動がほとんどないのが望ましい結果です。

仮想化環境に関する手順

VMWare

VMWare ESX を使用して仮想化環境を管理およびデプロイしている場合、MongoDB の動作に対応するために、ESX コンソールで次の設定を行ってください。

  1. メモリバルーンを無効にします。

  2. MongoDB データベースをホストする仮想マシンのメモリを事前に割り当てて確保します。

  3. Storage I/O Control を使用して、十分な I/O を mongod プロセスに割り当てます。

  4. CPU 予約を設定して、MongoDB をホストするマシンの CPU リソースを確保します。

  5. 準仮想化 I/O ドライバーの使用を検討します。その方法について詳しくは、こちらのナレッジベースの記事を参照してください。

Amazon Web Services

Amazon Web Services に MongoDB をセットアップする方法については、MongoDB web サイトの AWS 統合の設定に関する記事を参照してください。

デプロイ前に MongoDB をセキュリティで保護する

デプロイメント前にデータベースの設定を保護する方法についてのアドバイスは、MongoDB の安全なデプロイに関する投稿を参照してください。

Dispatcher

Dispatcher のオペレーティングシステムの選択

MongoDB デプロイメントが適切に機能するには、Dispatcher をホストするオペレーティングシステムが Apache httpd バージョン 2.4 以降​を実行している必要があります。

また、セキュリティへの影響を最小限に抑えるために、ビルドで使用されているすべてのライブラリが最新であることを確認してください。

Dispatcher 設定

一般的な Dispatcher 設定は、1 つの AEM インスタンスの 10 倍から 20 倍までの要求スループットに対応します。

Dispatcher は概してステートレスなので、水平方向に簡単にスケーリングできます。一部のデプロイメントでは、作成者が特定のリソースにアクセスできないように制限する必要があります。こうした理由から、オーサーインスタンスで Dispatcher を使用することを強くお勧めします。

Dispatcher を使用せずに AEM を実行するには、SSL ターミネーションとロードバランシングを別のアプリケーションで実行する必要があります。これが必要なのは、セッションには、セッションが作成された AEM インスタンスに対する親和性が必要であるからです。この概念は、スティッキー接続と呼ばれます。これは、コンテンツの更新にかかる遅延を最小限に抑えるためです。

設定方法について詳しくは、Dispatcher のドキュメントを参照してください。

その他の設定

スティッキー接続

スティッキー接続では、1 人のユーザーのパーソナライズされたページとセッションデータがすべて AEM の同じインスタンスで作成されます。このデータはインスタンスに格納されるので、同じユーザーからの後続の要求は同じインスタンスに戻ります。

AEM インスタンスに要求をルーティングするすべての内部レイヤーでスティッキー接続を有効にして、後続の要求が同じ AEM インスタンスに到達するようにすることをお勧めします。他の方法では、インスタンス間でコンテンツが更新される際に顕著な遅延が発生しますが、スティッキー接続を使用すると、遅延を最小限に抑えることができます。

長い有効期限

デフォルトでは、AEM Dispatcher から送信されたコンテンツには Last-Modified および Etag ヘッダーが含まれていますが、コンテンツの有効期限を示すものはありません。これにより、ユーザーインターフェイスは常にリソースの最新バージョンを取得しますが、リソースが変更されているかどうかを確認するためにブラウザーで GET 操作が実行されることも意味します。その結果、ページの読み込みに応じて、複数の要求に対して 304(Not Modified)の HTTP 応答が返されることがあります。有効期限がないことがわかっているリソースについては、Expires ヘッダーを設定して Last-Modified および ETag ヘッダーを削除すると、コンテンツがキャッシュされ、Expires ヘッダーの日付になるまで、それ以上の更新要求はおこなわれなくなります。

ただし、この方法を使用すると、Expires ヘッダーの有効期限に達する前にブラウザーでリソースを期限切れにするための適当な方法がなくなります。この問題を緩和するために、クライアントライブラリに不変の URL を使用するように HtmlClientLibraryManager を設定できます。

これらの URL が変更されることはありません。URL に含まれているリソースの本文が変更された場合、変更内容が URL に自動的に反映され、ブラウザーから適切なバージョンのリソースが要求されます。

デフォルト設定では、HtmlClientLibraryManager にセレクターが追加されます。セレクターがある場合、セレクターはそのままの状態でリソースが Dispatcher にキャッシュされます。さらに、このセレクターを使用して、有効期限の動作が適切になるようにすることもできます。デフォルトのセレクターでは、lc-.*?-lc というパターンが使用されます。次の Apache httpd 設定のディレクティブでは、このパターンと一致するすべての要求が、適切な有効期限を使用して処理されます。

Header set Expires "Tue, 20 Jan 2037 04:20:42 GMT" "expr=(%{REQUEST_STATUS} -eq 200) && (%{REQUEST_URI} =~ /.*lc-.*?-lc.*/)"
Header set Cache-Control "public, no-transform, max-age=267840000" "expr=(%{REQUEST_STATUS} -eq 200) && (%{REQUEST_URI} =~ /.*lc-.*?-lc.*/)"
Header unset ETag "expr=(%{REQUEST_STATUS} -eq 200) && (%{REQUEST_URI} =~ /.*lc-.*?-lc.*/)"
Header unset Last-Modified "expr=(%{REQUEST_STATUS} -eq 200) && (%{REQUEST_URI} =~ /.*lc-.*?-lc.*/)"
Header unset Pragma "expr=(%{REQUEST_STATUS} -eq 200) && (%{REQUEST_URI} =~ /.*lc-.*?-lc.*/)"

スニッフィングなし

content-type がないコンテンツが送信された場合、多くのブラウザーでは、コンテンツの最初の数バイトを読み取って、コンテンツのタイプを推測しようとします。これは、「スニッフィング」と呼ばれます。リポジトリに書き込むことができるユーザーがコンテンツタイプを指定せずに悪意のあるコンテンツをアップロードする可能性があるので、スニッフィングによってセキュリティ上の脆弱性が生じます。

そのため、Dispatcher で処理されるリソースに no-sniff ヘッダーを追加することをお勧めします。ただし、Dispatcher ではヘッダーはキャッシュされません。これは、ローカルファイルシステムから提供されたコンテンツのコンテンツタイプが、生成元の AEM サーバーの元の content-type ヘッダーではなく、拡張子によって特定されることを意味します。

キャッシュされたリソースを Web アプリケーションがファイルタイプなしで提供することがないとわかっている場合は、スニッフィングなしを有効にしても問題ありません。

スニッフィングなしは包括的に有効にすることができます。

Header set X-Content-Type-Options "nosniff"

また、選択的に有効にすることもできます。

RewriteCond %{REQUEST_URI} \.(?:js|jsonp)$ [OR]
RewriteCond %{QUERY_STRING} (callback|jsonp|cb)=\w+
RewriteRule .* - [E=jsonp_request:1]
Header set X-Content-Type-Options "nosniff"  env=jsonp_request
Header setifempty Content-Type application/javascript env=jsonp_request

コンテンツセキュリティポリシー

Dispatcher のデフォルト設定では、オープンなコンテンツセキュリティポリシー(CSP)が許可されます。これにより、ブラウザーサンドボックスのデフォルトポリシーが適用されるすべてのドメインからページにリソースを読み込むことができます。

信頼できない、または検証されていない外部サーバーから javascript エンジンにコードが読み込まれることを防ぐために、リソースの読み込み元を制限するようにしてください。

CSP では、ポリシーを微調整できます。ただし、複雑なアプリケーションでは、ポリシーの制限を厳格にしすぎると、ユーザーインターフェイスの一部が機能しなくなる可能性があるので、CSP ヘッダーを慎重に開発する必要があります。

メモ

この仕組みについて詳しくは、コンテンツセキュリティポリシーに関する OWASP のページを参照してください。

サイジング

サイジングについて詳しくは、ハードウェアのサイジングのガイドラインを参照してください。

MongoDB のパフォーマンスの最適化

MongoDB のパフォーマンスについての一般的な情報は、MongoDB のパフォーマンスの分析に関するページを参照してください。

既知の制限事項

同時インストール

MongoMK では、1 つのデータベースで複数の AEM インスタンスを同時に使用することがサポートされていますが、同時インストールはサポートされていません。

この制限を回避するには、まず 1 つのメンバーでインストールを実行し、最初のインストールが完了した後で、他のメンバーを追加します。

ページ名の長さ

AEM が MongoMK 永続性マネージャーのデプロイメントで実行されている場合、ページ名は 150 文字に制限されます。

メモ

MongoDB 自体の既知の制限やしきい値についても理解しておくために、MongoDB のドキュメントを参照してください

このページ