0

ログに記録された大量の情報の統計を個別のチャネルに分割して維持したいシステムがあります。各チャネルには、時間、日、月、年の最大値と最小値を含む統計をカスケード形式で維持する概要ドキュメントがあります。

チャネルの統計を 1 か月間保持する単一のドキュメントを維持できます。これには、1 か月の最大/最小、31 の毎日の最大/最小、およびそれらの日のそれぞれの 24 時間の最大最小が含まれます。

$inc を使用してドキュメントをカウントすることは、その場でのアトミックな更新に最適です。更新修飾子の $max と $min は問題を解決しますが、残念ながらそれは利用できません。

タスク プロセッサ内で最大値と最小値を保持し、$set を発行することはできますが、システム内のすべてのタスク プロセッサ (異なるマシン上にある可能性があります) を調整するのに問題があるため、mongo をメイン リファレンスとして保持することにしました。また、異なるタスク プロセッサ インスタンスで同時に実行されている 2 つの別個のタスクによって、同じ統計が更新されている可能性があります。

そのため、最善の解決策に関するコメント/提案を探しています(必ずしも生データを保持するとは限らないため、後処理はオプションではありません)

  1. 更新が必要になるたびに読み取り、更新、保存しますか?

  2. db Eval を使用して JavaScript サーバー側を実行し、単一の値を渡すだけで max/man カスケードを更新しますか?

  3. 別の方法はありますか?

助けてくれて本当にありがとうございます。

4

1 に答える 1

1

楽観的ロックを探していると思います。ドキュメントにバージョン フィールドを格納することで、更新がアトミックであることを確認できます。次の例を検討してください。

{_id: xyz, version: 2, max: 10}

最初にドキュメントを見つけます。

db.example.find({_id:xyz})

バージョン番号を保存し、最大値を更新する必要があるかどうかを (クライアント側で) 判断します。もしそうなら、

db.example.update({id:xyz, version: 2}, {$set: {max: 12}, $inc: {version: 1}})

クエリが実行されてから更新が行われるまでの間にバージョンが変更された場合、この更新は失敗するため、同時実行に関連するデータの破損が防止されます。getLastError を使用して、更新が失敗したかどうかを判断し、その後、ステップ 1 から再試行できます。

この操作にはグローバル ロックが必要なため、db.eval() は避ける必要があります。

楽観的ロックに関するその他のリソースは、http: //www.mongodb.org/display/DOCS/Atomic+Operations#AtomicOperations-%22UpdateifCurrent%22 http://code.google.com/p/morphia/wiki/にあります。 Mongoニュースレター記事Dec2010

並行性に関する MongoDB ドキュメント: http://www.mongodb.org/display/DOCS/How+does+concurrency+work

于 2012-07-06T17:43:58.440 に答える