web-dev-qa-db-ja.com

レプリカセットのMongoDBプライマリメンバーの高メモリ使用量

現在、シャーディングされたクラスターが稼働中であり、各レプリカセットのプライマリメンバーのメモリ使用量が8GBと非常に高いことに気付きました。

mongod --auth --bind_ip_all --shardsvr --replSet a --smallfiles --oplogSize 1024 --keyFile /file/somewhere/

(おそらく単純に)oplogSizeが使用するメモリの量を制限すると思った。

これを解決する方法、または私の方法のエラーを強調する方法に関するガイダンスは、高く評価されています。

1
Alex Johnston

前書き

oplog には 何もない メモリ消費とはほとんど関係ありません。 キャップ​​されたコレクション は、操作が他のレプリカセットメンバーにレプリケートされる 先読みログ の一種として使用されます。

一般的に、MongoDBは特に指示がない限り、最大85%(ギブアンドテイク)のメモリを使用します。このメモリは、RAM=)のインデックスと "ワーキングセット"(最近使用したドキュメントのコピー)を保持して最適なパフォーマンスを確保するために使用されます。技術的に RAMを制限することができます。これは Very Bad Idea™これを行うと、MongoDBのパフォーマンスが大幅に制限され、RAMが不十分なためにスケールアウトまたはスケールアップするタイミングを検出できなくなります。

TL; DR:MongoDBで使用されるRAMを制限する方法を尋ねる必要がある場合は、この手順で発生する副作用を判断できないため、制限しないでください。

MongoDBのメモリ消費の制限

基本的に3つのオプションがあります: キャッシュサイズWiredTigers ストレージエンジンの場合は cgroups を使用してメモリを制限しますmongod can OSから要求するか、Dockerを使用してそれを実行します(これにより少し簡単になりますが、内部ではDockerがcgroupを使用します。iirc)。

オプション1:WiredTigerのキャッシュサイズを制限する

次のオプションを構成ファイルに追加します(YAML形式であると想定しています)。

storage:
 wiredTiger:
  engineConfig:
     cacheSizeGB: <number>

ここで、<number>はRAM MongoDBがWiredTigerのキャッシュにを使用することを許可されていますの最大量です。このパラメーターを操作すると、 severly はパフォーマンスに影響します(一方、MongoDBのメモリ消費量は常に制限されます)。これは、mongod自体が使用するメモリを制限しないことにも注意してください(たとえば、それぞれ接続には小さなスタックが割り当てられます)。

オプション2:cgroupを使用してmongodの全体的なメモリ消費を制限する

Rootユーザーとして、最初にcgroupが有効になっていることを確認します。

$ lscgroup
cpuset:/
cpu:/
cpuacct:/
memory:/
devices:/
freezer:/
net_cls:/
blkio:/

Cgroupが使用可能であると想定して、MongoDBのメモリ消費のコントロールグループを/etc/cgconfig.confで構成できるようになりました。

group mongodb{
    memory {
        memory.limit_in_bytes = 512m;
    }
}

その後、cgconfigサービスを再起動する必要があります。上記の設定を単純にコピーして貼り付けないでください。512MBを使用すると、MongoDBは(もしあれば)実行されます。 2GB以上のRAMを使用して、必要に応じてメモリ制限を調整します。

次に、作成したコントロールグループにmongodを割り当てる必要があります。そのためには、/etc/cgrules.confを編集する必要があります。

*:mongod memory mongodb/

ここで、*は、誰がmongodを開始したかに関係なくこのルールが適用されることを示し、制限はコントロールグループmongod/のルールに従ってRAMに適用されます。最後のステップとして、cgredおよびMongoDBサービスを再起動する必要があります。mongodは、指定された量のRAMのみを使用する必要があります。

オプション3:Dockerを使用してmongodの全体的なメモリ消費を制限します。

  1. 現在実行しているMongoDBのバージョンを特定する

    $ mongod -version
    db version v3.4.10
    git version: 078f28920cb24de0dd479b5ea6c66c644f6326e9
    OpenSSL version: OpenSSL 1.0.2n  7 Dec 2017
    allocator: system
    modules: none
    build environment:
       distarch: x86_64
       target_Arch: x86_64
    

    出力は異なる場合がありますが、db version、つまりマイナーバージョンのみが必要です。この例では、「3.4」です。

  2. 適切なDockerイメージをプルする

    $ docker pull mongo:3.4
    

    以前に決定したバージョンのDockerイメージをプルし、プルしたイメージを次のステップで使用する必要があります。

  3. 適切なパラメーターを使用してDockerイメージを実行する

     $ docker run -d --name mongod --memory=512m \
     > --mount type=bind,src=/path/to/your/datafiles,dst=/data/db \
     > --mount type=bind,src=/file/somewhere/,dst=/key.file,readonly
     > mongod <yourOptions>
    

    ここで注意すべき点:最初のmountは既存のデータファイルにコンテナ内からアクセスできるようにし、2番目のmountはキーファイルに対して同じことを行います。それに応じてmongodオプションを調整する必要があります。つまり、keyFileオプションは、キーファイルをマウントした宛先を指すようにします。詳細は docker documentation および mongo docker imageのREADME を参照してください。

結論

シャードされたクラスターがあり、個々のシャードメンバーのメモリ消費を制限したい。

本番システムの場合、これは Very Bad Idea™です。 mongodsを実行しているマシンで実行されている他のサービス(高負荷の場合に2つのサービスがリソースを競合させる)、または(上記の方法を使用して)MongoDBが提供するパフォーマンスを人為的に制限します。これは悪いシステム設計です。なぜ最初から破片を作ったのですか?シャーディングは、MongoDBのロードバランシングとスケールアウトの方法です(RAMのような制限要因がこれ以上スケールアップできない場合は、費用に見合うだけの効果が得られないためです)。私は、お客様に繰り返し(そして正直に言えば自分にも)マントラを持っています。

本番データを保持するMongoDBインスタンスは、専用マシンで実行する必要があります。例外なく!

最初にシャーディングした理由とシャードの数によっては、専用のマシンでクラスターを実行した場合はシャーディングする必要がなかった可能性もあります。計算する。

また、クラスターノードで他のサービスを実行するのが良いアイデアであったとしても、それらは明らかにプロビジョニング不足です。 RAMのパフォーマンスが低下した場合と比較すると、基本的には、マシンをRAMに制限するのではなく、適切な量にスケールアップすることは簡単です。そもそも悪いシステム設計を人為的に強制する。

あなたへの私のアドバイスは、上記のアプローチのいずれにも従わないことです。代わりに、専用マシンでMongoDBインスタンスを含むデータを実行します。シャーディングする前に、バックRAMおよびIO-wise(CPUはめったに問題となることはめったにありません))に応じた強さを得る限り、それらをスケールアップします。この執筆時点では、 128GBと256GB RAMとRAID 0(レプリカセットがある場合は、持っていますよね)またはRAID 10(シャードがレプリカセットでない場合-恥ずかしいです;))SSDの場合。

  • 単一のマシンで処理するにはIOPSが多すぎる
  • より多くのRAMが必要です)
  • 単一のマシンで保持できるよりも多くのデータがあります。

hth

PS RAM for the mongods。

1

MongoDB BOLに従ってここ レプリカセットメンバーを初めて起動すると、MongoDBはデフォルトサイズのoplogを作成します。

UnixおよびWindowsシステムの場合

デフォルト oplog sizeはストレージエンジンによって異なります。

Storage Engine              Default Oplog Size    Lower Bound   Upper Bound
In-Memory Storage Engine    5% of physical memory   50 MB       50 GB
WiredTiger Storage Engine   5% of free disk space   990 MB      50 GB
MMAPv1 Storage Engine        5% of free disk space  990 MB      50 GB

64ビットmacOSシステムの場合

デフォルトのoplogサイズは192 MBストレージエンジンに応じて、物理メモリまたは空きディスク領域のいずれか:

Storage Engine              Default Oplog Size
In-Memory Storage Engine    192 MB of physical memory
WiredTiger Storage Engine   192 MB of free disk space
MMAPv1 Storage Engine       192 MB of free disk space

ほとんどの場合、デフォルトのoplogサイズで十分です。たとえば、oplogが空きディスク領域の5%であり、24 hours of operationsの場合、セカンダリは、古くなりすぎて複製を続行できなくなることなく、最大24時間、oplogからのエントリのコピーを停止できます。ただし、ほとんどのレプリカセットの操作ボリュームははるかに少なく、oplogsはより多くの操作を保持できます。

注:New in version 3.6.

この手順では、 replSetResizeOplog コマンドを使用して、レプリカセットの各メンバーのoplogのサイズを変更します。 secondary メンバーで開始してから primary に進みます=。

重要:replSetResizeOplogを実行できるのは、Wired Tigerストレージエンジンで実行されているレプリカセットメンバーのみです。

レプリカセットメンバーに接続します

Mongoシェルを使用してレプリカセットメンバーに接続します。

mongo --Host <hostname>:<port>

注:レプリカセットが authentication を適用する場合、ローカルデータベースを変更する権限を持つユーザーとして認証する必要があります。 clusterManager または clusterAdmin role

oplogの現在のサイズを確認します

use local
db.oplog.rs.stats().maxSize

MaxSizeフィールドには、コレクションサイズがバイト単位で表示されます。

レプリカセットメンバーのoplogサイズを変更する

サイズを変更するには、 replSetResizeOplog を実行して、必要なサイズをメガバイト単位でサイズパラメータとして渡します。指定するサイズは、990または990メガバイトより大きくなければなりません。

次の操作は、レプリカセットメンバーのoplogサイズを16ギガバイト、つまり16000メガバイトに変更します。

db.adminCommand({replSetResizeOplog: 1, size: 16000})
0