0

私はMonogDBでこのようなことを達成しようとしています:

require 'base64'
require 'mongo'

class MongoDBQueue

  def enq(thing)
    collection.insert({ payload: Base64.encode64(Marshal.dump(thing))})
  end
  alias :<< :enq

  def deq
    until _r = collection.find_and_modify({ sort: {_id: Mongo::ASCENDING}, remove: true})
      Thread.pass
    end
    return Marshal.load(Base64.decode64(_r["payload"]))
  end
  alias :pop :deq

  private

    def collection
      # database, collection & mongodb index semantics here
    end

end

当然のことながら、利用可能なメモリを破壊しないディスクでバックアップされたキューが Ruby に必要です。これを、デフォルトでクラスを使用する Anemone Web スパイダー フレームワークで使用しています。クラスQueueを使用できるフォークがありますが、 「ページキュー」と「リンクキュー」SizedQueueSizedQueue両方で、おそらくページをデキューして処理しようとしているためにデッドロックが発生することが多く、新しいリンクが見つかり、その状況を調整できません。

Redis キューの既存の実装もありますが、このマシンで使用可能なメモリをすべて使い果たします (使用可能なメモリは 16Gb であるため、簡単ではありません)。

そのため、この MongoDB バックエンドを使用したいのですが、実装が非常識だと思います。恐ろしい解決策のThread.passように感じますが、Anemone はマルチスレッドであり、MongoDB は読み取りのブロックをサポートしていないため、トリッキーな状況です。

ここに私の参照があります:

質問:

  • これがどれほど正気であるかについて、誰でもコメントできますかsleep?sleep
  • 私はおそらくすべきでしょうThread.passsleep?(そうではないと思います、上記を参照してください)
  • MongoDB ブロックから読み取るようにできますか? ここでその話がありましたが、何も起こりませんでした: https://groups.google.com/forum/?fromgroups=#!topic/mongodb-user/rqnHNFXaZ0w
4

2 に答える 2

0

1) MongoDB での読み取りがブロックされています。findOne() または findAndModify() を実行すると、クライアント側にデータが存在するまで呼び出しは返されません。find() を実行すると、カーソルを取得するまで呼び出しは返されません。その後、必要なだけカーソルを反復処理できます。

2) デフォルトでは、MongoDB への書き込みは「ファイア アンド フォーゲット」です。データの整合性を気にする場合は、接続、データベース、またはコレクション オブジェクトで :safe => true を設定して安全な書き込みを行う必要があります。

于 2012-10-03T23:46:11.550 に答える
0

Kernel.sleep は、実際にはより良い解決策です。それ以外の場合は、そこでスピンします (ただし、各クエリの後に他のスレッドに制御を渡します)。findAndModify はアトミックであるため、(JRuby でも) 1 つのスレッドのみがジョブを実行するため、ここでの「ブロッキング」の問題が何であるかがよくわかりません。

于 2012-10-17T23:34:01.090 に答える