2017-05-25 9 views
1

私は複数のノードプロセスがドキュメントを読み書きするmongodbデータベースを持っています。私はどのようにして一度に1つのプロセスだけがドキュメント上で作業できるようにすることができるのかを知りたいと思います。プロセスがそのエントリの更新を完了した後に解放されるロック(ある種のロック)。複数のプロセスからのMongodbクエリ。アトミック性を実装する方法

私のアプリケーションは、次のことを行う必要があります。

  • ウォークをカーソルで一つの各エントリ1通過。
  • (これは他のプロセスがそれに取り組むことができませんエントリをロック)

  • サードパーティのサイトから情報を取得します。

  • 新しい情報を計算してエントリを更新します。
  • (文書のロックを解除します)

また、文書のロックを解除した後、数時間のためにそれを更新するために、他のプロセスは必要ないでしょう。

その後、データベースの負荷を軽減できるように、複数のmongodbクラスタを設定したいと考えています。そのため、ソリューションは単一および複数のデータベースサーバーに適用する必要があります。少なくとも、複数のmongoサーバーを使用しています。

MongoDB documentationパー
+0

アプリケーション層で[悲観的なロック](https://en.wikipedia.org/wiki/Record_locking)を実装する必要があります。 –

+0

件名を詳しく記入して回答を投稿できますか? – Azarus

+0

申し訳ありませんが、詳細は何もありません。 Mongodbはトランザクションをサポートしていないので、自分で実装するか、npmパッケージを使用する必要があります。前者はStackOverflow形式では広すぎ、後者は非常に少数であるためかなり意見があります。あなたがパッケージの1つを試して、いくつかのコーディングの問題に直面するなら、それはより適切な質問でしょう。 –

答えて

1

ないエレガントなソリューションロックを含む:

  • versionプロパティをドキュメントに追加します。

  • ドキュメントを更新するときは、versionプロパティを増やします。

  • ドキュメントを更新するときは、最後に読み取ったversionを検索クエリに含めます。ドキュメントが他の場所で更新されている場合、検索クエリは結果を得ず、更新は失敗します。

  • 更新が失敗した場合は、操作を再試行できます。

私はこのパターンを過去に大きな成功を収めて使用しました。

は、ドキュメント{_id: 123, version: 1}を持っている想像してみてください。

ここで、db.collection.findAndModify({ query: {_id: 123, version: 1}, update: { $inc: 1 }});を同時に実行している3人のMongoクライアントがいるとします。

最初の更新が適用され、残りは失敗します。どうして?今度はversion2であり、queryversion: 1であるからです。

+0

これは、レプリケーションのためにセットアップされた複数のデータベースサーバーでどのように機能しますか?これは、各ドキュメントのブール値を設定するだけとはどのように違いますか? (bool WorkingOnIt;)2番目のデータベースサーバーにレプリケートされますが、もう1つのプロセスはこのサーバーから読み取っています。 – Azarus

+0

私は誰が誰に、なぜなぜ答えをアップアップしたのか解明してください。これはなぜ解決策であり、どのように複製されたサーバ上で動作するのですか? – Azarus

+0

これで最初の更新が成功すると残りは無効になります。それをレスポンスに追加しましょう。 – arboreal84

1

isolated: Prevents a write operation that affects multiple documents from yielding to other reads or writes once the first document is written... $isolated operator causes write operations to acquire an exclusive lock on the collection...will make WiredTiger single-threaded for the duration of the operation.あなたが複数のドキュメントを更新しているのであれば、あなたは最初に、サードパーティのAPIからデータを取得し、たとえば配列に情報を解析して、モンゴシェル内でこのようなものを使用することができます

db.foo.update(
    { status : "A" , $isolated : 1 }, 
    { $set: { < your key >: < your info >}}, //use the info in your array 
    { multi: true } 
) 

また、ドキュメントを1つずつ更新する必要がある場合は、MongoDBのノードドライバのfindAndModify()またはupdateOne()を使用できます。 MongoDB documentation 'に注意してください。単一のドキュメントを変更する場合、findAndModify()メソッドとupdate()メソッドの両方がドキュメントをアトミックに更新します。

一つ一つを更新する例:最初にあなたconnect to the Mongod with the NodeJS driver、その後connect to the third part API using NodeJS's Request module, for examplemodify your documentsにデータを使用する前に、データを取得し、解析し、以下のようなもの:

var request = require('request'); 

var MongoClient = require('mongodb').MongoClient, 
    test = require('assert'); 

MongoClient.connect('mongodb://localhost:27017/test', function(err, db) { 
    var collection = db.collection('simple_query'); 
    collection.find().forEach(
     function(doc) { 
      request('http://www.google.com', function(error, response, body) { 
       console.log('body:', body); // parse body for your info 
       collection.findAndModify({ 
        <query based on your doc> 
       }, { 
        $set: { < your key >: < your info > 
        } 
       }) 
      }); 
     }, function(err) { 
     }); 
    }); 
+0

これまでのところ、私は実際にはどのように動作するのか分かりません。今は、第三者のアプリケーション(Webアプリケーション)からのプロセスに対して、タスクを1つずつ割り当てることができました。また、その間にアプリを多く最適化し、答えを待っていて、しばらくスケーリングが必要なように見えます。とにかく、あなたはもう少し感謝の答えを詳しく述べることができます。 – Azarus

+0

簡単な検索と更新の例がありますか?それ以来、実際に私のアプリは何をしているのですか? – Azarus

+0

例が追加されました。ドキュメントやAPIの詳細を提供すれば、その具体例はより具体的になります。 –

関連する問題