4

私の MongoDB コレクションはジョブ キューとして使用され、このコレクションから読み取る 3 つの C++ マシンがあります。問題は、この 3 人が同じ仕事をすることができないことです。すべてのジョブは 1 回だけ実行する必要があります。

「isDone:False」ですべてのレコードのコレクションを検索して未完了のジョブをすべて取得し、このドキュメント「isDone:True」を更新します。しかし、2 台のマシンが同じドキュメントを同時に見つけた場合、両方とも同じジョブになります。どうすればこれを回避できますか?

編集: 私の質問は - findAndModify は本当にその問題を解決しますか? (MongoDbのfindAndModifyで排他的な読み取りを確保する方法を読んだ後?

4

2 に答える 2

1

はい、findAndModify で解決します。

参照:複数のクライアントからの MongoDB findAndModify "... 注: このコマンドは、影響を受けるデータベースの書き込みロックを取得し、完了するまで他の操作をブロックします。ただし、通常、書き込みロックは短命であり、他の同様の update() と同等です。オペレーション。 ..."

参照: http://docs.mongodb.org/manual/reference/method/db.collection.update/#db.collection.update "... 分割されていないコレクションの場合、この動作を $isolated 分離演算子でオーバーライドできます。これにより、更新操作が分離され、更新中に他の書き込み操作がブロックされます。分離演算子を参照してください。...」

参照: http://docs.mongodb.org/manual/reference/operator/isolated/

よろしく、 モアシー

于 2013-04-24T02:09:54.243 に答える
1

はい、検索と変更で問題が解決します。

db.collection.findAndModify( { query: { isDone: false }, update: { $set: { isDone: true } }, new: true, upsert: false # 新しいドキュメントを作成しない } );

これにより、false から true に更新されたばかりの単一のドキュメントが返されます。

しかし、C++ クライアントに問題が発生した場合 (ボックスが停止する、強制終了される、コードにエラーが発生するなど)、重大な問題が発生します。サーバーの更新直後で、C++ クライアントが更新される前に、TCP 接続が切断された場合を想像してみてください。コードが機能します。一般に、マルチフェーズ アプローチを採用することをお勧めします。

  • 「isDone」を「isInProgress」に変更し、完了したらドキュメントを削除します。(これで、"todo" と "beulding" のスタックが表示されます。何かが長時間 "doed" されている場合、クライアントは死亡した可能性があります。

  • 「isDone」を「phase」に変更し、原子的に「new」から「started」に設定します(後で「finished」に設定します)。これで、何かが長時間「開始」されているかどうかを確認できます。クライアントが停止した可能性があります。

あなたが本当に洗練されているなら、部分的な索引を作ることができます。たとえば、「"phase:{ $ne: 'finished'}" のドキュメントのみをインデックス化します。これで、数百万の完成したドキュメントのインデックス作成にスペースを浪費する必要がなくなりました。インデックスは、少数の新規/進行中のドキュメントのみを保持します。 、したがって、より小さく/より高速です。

于 2013-04-24T02:40:26.660 に答える