11

ジャーナリングがオンになっている場合でも、MongoDB で書き込みが失われる可能性はありますか?

「デフォルトでは、失われた書き込みの最大の範囲、つまり、ジャーナルに対して行われなかったものは、最後の 100 ミリ秒で行われたものです。」

これはManage Journalingによるもので、最後にジャーナルがディスクにフラッシュされてから行われた書き込みが失われる可能性があることを示しています。

より耐久性が必要な場合は、「mongod がより頻繁にジャーナルにコミットするように強制するには、j:true を指定できます。j:true を使用した書き込み操作が保留中の場合、mongod は journalCommitInterval を設定値の 3 分の 1 に減らします。」

この場合でも、ジャーナルのディスクへのフラッシュは非同期であるように見えるため、書き込みが失われる可能性はまだあります。書き込みが失われないことを保証する方法について何か不足していますか?

4

5 に答える 5

3

多分。はい、データが書き込まれるのを待ちますが、ドキュメントによると、「書き込み操作が完全に永続的でない場合、ジャーナルコミットの間にウィンドウがあります」とあります。彼らが何を指しているのかわかりませんでした。

編集した回答をここに残しておきますが、自分自身を前後に逆にしたので、少しイライラします:


引くことができるレバーがたくさんあるので、これは少し注意が必要です。

MongoDB のセットアップ

ジャーナリングが有効になっていると仮定すると (64 ビットのデフォルト)、ジャーナルは定期的にコミットされます。のデフォルト値はjournalCommitInterval、ジャーナルとデータ ファイルが同じブロック デバイスにある場合は 100 ミリ秒、そうでない場合は 30 ミリ秒です (したがって、ジャーナルを別のディスクに置くことをお勧めします)。

を 2 ミリ秒に変更することもできますがjournalCommitInterval、書き込み操作の数が増え、全体的な書き込みパフォーマンスが低下します。

書き込み懸念

データがディスクに書き込まれるまで待機するようにドライバーとデータベースに指示する書き込み懸念を指定する必要があります。ただし、これは、データが実際にディスクに書き込まれるまで待機しません。これは、デフォルトのセットアップでは、最悪のシナリオでは 100 ミリ秒かかるためです。

したがって、最良の場合でも、データが失われる可能性がある 2 ミリ秒のウィンドウがあります。ただし、多くのアプリケーションにとっては不十分です。

このfsyncコマンドは、すべてのデータ ファイルのディスク フラッシュを強制しますが、ジャーナリングを使用する場合は不要であり、非効率的です。

実際の耐久性

すべての書き込みをジャーナルに記録したとしても、データセンターの管理者が都合の悪い日を過ごしてハードウェアにチェーンソーを使用したり、ハードウェアが単に分解したりした場合、何の役に立つでしょうか?

RAID のようなブロック デバイス レベルではなく、はるかに高いレベルでの冗長ストレージは、多くのシナリオでより適切なオプションです。レプリカ セットを使用してデータを別の場所または少なくとも別のマシンに置き、w:majorityジャーナリングを有効にして書き込み懸念を使用します。 (ただし、ジャーナリングはプライマリにのみ適用されます)。個々のマシンで RAID を使用して運を高めましょう。

これにより、パフォーマンス、耐久性、一貫性の最適なトレードオフが実現します。また、書き込みごとに書き込みの懸念を調整でき、可用性が高くなります。3 台の異なるマシンで次の fsync のためにデータがキューに入れられている場合、どのマシンでも次のジャーナル コミットまでに 30 ミリ秒かかる可能性がありますが (最悪の場合)、30 ミリ秒の間隔で 3 台のマシンがダウンする可能性はおそらく 100 万倍になります。 chainsaw-massacre-admin シナリオよりも低い。

証拠

TL;DR: 上記の私の答えは正しいと思います。

ドキュメントは、特に に関しては少しいらいらする可能性があるwtimeoutため、ソースを確認しました。私はmongoソースの専門家ではないので、これを一粒の塩で取ってください:

ではwrite_concern.cpp、次のことがわかります (簡潔にするために編集されています)。

if ( cmdObj["j"].trueValue() ) {
    if( !getDur().awaitCommit() ) {
        // --journal is off
        result->append("jnote", "journaling not enabled on this server");
    } // ...
}
else if ( cmdObj["fsync"].trueValue() ) {
    if( !getDur().awaitCommit() ) {
        // if get here, not running with --journal
        log() << "fsync from getlasterror" << endl;
        result->append( "fsyncFiles" , MemoryMappedFile::flushAll( true ) );
    }

MemoryMappedFile::flushAll( true )が設定されている場合の呼び出しに注意してくださいfsync。この呼び出しは明らかに最初の分岐ではありません。それ以外の場合、持続性は別のスレッドで処理されます (関連するファイルには接頭辞 が付きますdur_)。

これはwtimeout、スレーブを待機する時間を指し、サーバー上の I/O や fsync とは何の関係もありません。

于 2013-08-28T13:29:15.030 に答える
0

一般に、失われた書き込みは、OS レベルであっても、システムのランタイムと永続的な (不揮発性) ストレージとの間でバッファリング/キャッシュ/遅延書き込みが関係するすべてのシステムで問題になります (たとえば、後書きキャッシュ)。したがって、具体的なプロバイダー (MongoDB) がトランザクションの耐久性のための機能を提供している場合でも、書き込みを失う可能性は常にあります。最終的にデータを書き込むのは基盤となる OS であり、その場合でもデバイス レベルでのキャッシュがあります...そしてそれは単なる下位レベルであり、システムを高度に同時実行、分散、およびパフォーマンス化すると、事態は悪化するだけです。

要するに、絶対的な耐久性はありません。特に Mongo のような NoSQL ストレージでは、実用的/最終的/最高の耐久性しかありません。Mongo は、そもそも一貫性と耐久性のために作られていません。

于 2013-08-28T13:33:41.377 に答える