0

mongodb にシャードされたドキュメントのコレクションがあり、それにアクセスするいくつかのアプリケーション サーバーがあります。

各アプリケーションは新しいドキュメントを提供し、最終的には一部を削除する必要があります。

どのドキュメントが削除されるかは問題ではありませんが、正確な数を削除 (クレーム) し、他のアプリケーションが同じドキュメントを削除 (クレーム) していないことが重要です。

私の考えは:

unique = makeUniqueValue()
docs = []

for (i = 0;i < 10;i++) {
    r = findAndModify( claim: false, $set: { claim: unique });
    if (r.value) docs.push(r);
}

if (docs.length < 10)
    "release all docs by updating (claim: false) and try again in some time"

このソリューションの潜在的な問題の 1 つは、アプリケーションが多すぎる (およびドキュメントが少ない) 場合、アプリケーションがいくつかのドキュメントを要求して再度リリースし続けることです。

この問題に対するよく知られており、十分にテストされた解決策は何ですか?

「update」と「findAndModify」は、更新されたドキュメントが更新前のクエリと一致することを保証していますか?

または、別のアプリケーションが照合と更新の間にそれを「盗み」、両方のアプリケーションがドキュメントを主張したと考える可能性がありますか?

4

1 に答える 1

1

そのドキュメントで更新が実行されると、クエリがドキュメントと一致し、それが最新バージョンであることを確認します。

他のプログラムは、ドキュメント単位で盗むことはできません。

この答えがむき出しであることに気付いたので、もう少し説明します。MongoDB には、データベース レベルでライターの貪欲な読み取り/書き込みロックがあります。

これはfindAndModify、書き込み操作を実行する権限が与えられている間、 が何かを見つけることができないことを意味します。そのため、たとえば別のスレッド/アプリケーションで要求されているように更新されようとしているドキュメントを見つけることができません。

そのため、このコードは、ドキュメントの要求を 1 つのアプリケーションに即座に分離します。これは、別のアプリケーションによるループの各反復により、要求されていないドキュメントが発生し、MongoDB サーバー上で中間/部分的な状態になることは決してないためです。

これらのドキュメントは更新する必要があるドキュメントであることがわかっているため、実際に更新する場合は問題ではありませんが、そのような更新操作自体は部分的なドキュメント状態を取ることができないため、 etc のような演算子は$set単一のドキュメントに対して順番に実行されます。claim falseなし。更新では、書き出された静的な結果セットからではなく、データ ファイルから直接行が選択されます。

_idまたは別の静的データを使用して更新する場合は、状況が異なります。

于 2014-02-01T16:32:03.247 に答える