MongoDB作为队列,有上限的集合+可尾游标

Posted

技术标签:

【中文标题】MongoDB作为队列,有上限的集合+可尾游标【英文标题】:MongoDB as a queue, capped collection + tailable cursor 【发布时间】:2012-08-18 08:33:08 【问题描述】:

(在 mongo-user 讨论组 https://groups.google.com/d/topic/mongodb-user/i1ge4bNiMgM/discussion 上提问)

您好,我想将 MongoDB 用作消息队列,并考虑为此目的使用上限集合 + 可尾游标。 我知道可尾光标可用于按插入顺序访问文档,但是

    我可以对光标使用任何排序顺序吗? 尾标是否可以与过滤查询一起使用(跳过一些我不想处理的文档)?如果是这样,它如何处理新文档的插入 - 只有当新文档符合查询条件时才会通知我? C# 驱动程序是否完全支持尾随游标? 我希望我的队列保证单次传递 - 我的意思是如果两个客户端尝试从同一个集合中读取消息,他们不应该能够“使用”相同的消息。我认为这可以通过 findAndModify 来实现,但是如何使用拖尾光标来实现呢?

谢谢 RG

【问题讨论】:

【参考方案1】:

AOL/About.me 于 2012 年 4 月在硅谷 MUG 上发表了关于“MongoDB as message queue”的演讲,您可能会发现它有助于规划您的方法。

    我可以对光标使用任何排序顺序吗? 尾标是否可以与过滤查询一起使用(跳过一些我不想处理的文档)?如果是这样,它如何处理新文档的插入 - 只有当新文档符合查询条件时才会通知我?

可尾游标尾随封顶集合的end,并且仅以自然顺序。如果您需要排序顺序,则需要使用索引查询。

请阅读Create Tailable Cursor 文档页面了解更多信息。

C# 驱动程序是否完全支持尾随游标?

是的,可尾光标支持已在 1.1 C# 驱动程序中实现(请参阅:code example)。

我希望我的队列保证单次传递 - 我的意思是,如果两个客户端尝试从同一个集合中读取消息,他们不应该能够“使用”同一条消息。我认为这可以通过 findAndModify 来实现,但是如何使用拖尾光标来实现呢?

有几种方法:

让一个带有可尾光标的读取器将任务分配给工作线程(即基于工作队列深度或循环)。这将比拥有多个阅读器更有效,但可能会出现单点故障。 (@Contango 在下面的评论中建议)拥有多个阅读器,但使用乐观并发确保只有一个工作人员“拥有”每个任务。这将导致更多的 I/O,但如果工作人员也直接拖尾,则可能会简化您的设计。

有关原子操作的更多信息,请参阅 MongoDB 手册中的Isolate Sequence of Operations。

【讨论】:

谢谢,我想这解释了为什么使用可尾光标的例子这么少 代码示例似乎已关闭。我在这里反映了它:gist.github.com/tekmaven/5842521 我不同意“根据您的用例,我认为可尾游标不是一种有用的方法。”的说法。它可以使用与乐观并发使用相同的原理来完成。每个消费者在它刚刚读取的项目上增加一个序列号,然后只写回序列号。如果序列号返回为 1,则消费者拥有它。如果它以两个或更多的形式返回,则消费者将其丢弃。这是因为每个单独的记录在 Mongo 中默认被锁定。我可能需要编写一些代码来演示这个。 @Contango:您当然可以为多个阅读器使用某种乐观并发(如您所建议的那样),但这似乎效率不高。不过,那里的声明肯定太宽泛了。我认为最好让一名读者跟踪并向多名工人分发任务。我认为我对可拖尾光标的评论更多地与想要按排序顺序拖尾有关,但那是几年前的事了:)。 每个尾随阅读器本质上都是在轮询,对吗?如果是这种情况(正如我所阅读和观察到的那样),那么我认为多个拖尾阅读器只会让系统陷入困境。我说的对吗?

以上是关于MongoDB作为队列,有上限的集合+可尾游标的主要内容,如果未能解决你的问题,请参考以下文章

Mongo 可尾游标与 Redis 发布/订阅

node-mongodb-native - 游标在每次调用期间返回 null 作为最后一个值

Java MongoDB FindOne 获取最后插入的记录

GraphQL 和 MongoDB 游标

“uncap”一个上限的MongoDB集合

一日一技:如何把MongoDB作为循环队列