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 网络蜘蛛框架一起使用,默认情况下使用Queue该类,有一个可以使用SizedQueue该类的 fork,但是当使用aSizedQueue对于“页面队列”和“链接队列”,它经常死锁,大概是因为它试图使一个页面出队并处理它,并且它找到了新的链接,这种情况无法调和。

还有一个 Redis 队列的现有实现,但是这也耗尽了我在这台机器上的所有可用内存(可用内存为 16Gb,所以这不是微不足道的)

正因为如此,我想使用这个 MongoDB 后端,但我认为实现很疯狂。感觉就像一个可怕的Thread.pass解决方案,但 Anemone 是多线程的,而且 MongoDB 不支持阻塞读取,所以这是一个棘手的情况。

以下是我的参考资料:

问题:

  • 任何人都可以评论这是多么理智,相比之下sleep(这应该触发VM将控制权传递给下一个线程,无论如何,但sleep感觉更脏)
  • 我应该也许Thread.passsleep?(我猜不是,见上文)
  • 我可以从 MongoDB 块中读取吗?这里有人谈论过,但从未谈过任何事情:https ://groups.google.com/forum/?fromgroups=#!topic/mongodb-user/rqnHNFXaZ0w
4

2 回答 2

0

Kernel.sleep 实际上是一个更好的解决方案,否则您将在那里旋转(尽管在每次查询后将控制权传递给其他线程)。由于 findAndModify 是原子的,因此只有一个线程(即使在 JRuby 上)会承担这项工作,所以我不太明白这里的“阻塞”问题是什么。

于 2012-10-17T23:34:01.090 回答
0

1) MongoDB 中的读取是阻塞的。如果您执行 findOne() 或 findAndModify(),则调用将不会返回,直到数据出现在客户端。如果您执行 find(),则调用不会返回,直到您获得游标:然后您可以根据需要在游标上迭代。

2) 默认情况下,写入 MongoDB 是“一劳永逸”。如果您关心数据完整性,则需要通过在连接、数据库或集合对象中设置 :safe => true 来进行安全写入

于 2012-10-03T23:46:11.550 回答