我使用现有数据库中的数据。这个数据库存储系统事件。我的服务应该通过计时器检查这个数据库,检查是否创建了一些新事件,然后上传并处理。类似于简单的队列实现。
问题是 - 当我检查数据库时,如何每次都获得新文档。我不能使用时间戳,因为事件从不同的来源进入数据库,并且事件没有任何顺序。所以我只需要使用插入订单。
我使用现有数据库中的数据。这个数据库存储系统事件。我的服务应该通过计时器检查这个数据库,检查是否创建了一些新事件,然后上传并处理。类似于简单的队列实现。
问题是 - 当我检查数据库时,如何每次都获得新文档。我不能使用时间戳,因为事件从不同的来源进入数据库,并且事件没有任何顺序。所以我只需要使用插入订单。
有几个选项。
如果它与您的用例匹配,第一个也是最简单的方法是使用上限集合。封顶集合是一个预定义大小的集合,充当一种环形缓冲区。一旦收集已满,它就会开始覆盖文档。为了迭代集合,您只需创建一个“tailable”光标,您将需要某种方式来识别“最后处理的文档”(即使文档中的一个简单的“done”标志也可以工作,但在插入文档时它必须存在) . 如果您确实无法以任何方式修改文档,那么您甚至可以将最后处理的文档保存在某个地方并使用课程时间戳(近似起始位置)并在处理更多文档之前查找最后一个文档。
此解决方案唯一真正的问题是您可以在集合中写入的文档数量受到限制,并且它不会随着时间的推移而增长。您可以对文档执行的写操作有限制(它们不能增长),但听起来不像是在修改文档。
第二种更复杂的选择是使用 oplog。对于独立配置,您仍需要传递 -replSet 选项来创建和使用 oplog。您将不会配置 oplog。在分片配置中,您需要分别跟踪每个“副本集”。oplog 包含一个文档,用于对服务器上的所有集合/文档执行的每个插入、更新、删除操作。每个条目都包含一个时间戳、操作和 id(至少)。以下是每个示例。
插入
{ "ts" : { "t" : 1362958492000, "i" : 1 },
"h" : NumberLong("5915409566571821368"), "v" : 2,
"op" : "i",
"ns" : "test.test",
"o" : { "_id" : "513d189c8544eb2b5e000001" } }
删除
{ ... "op" : "d", ..., "b" : true,
"o" : { "_id" : "513d189c8544eb2b5e000001" } }
更新
{ ... "op" : "u", ...,
"o2" : { "_id" : "513d189c8544eb2b5e000001" },
"o" : { "$set" : { "i" : 1 } } }
时间戳在服务器上生成,并保证单调递增。这使您可以快速找到感兴趣的文档。
此选项是最强大的,但需要您做一些工作。
我编写了一些演示代码来在一个集合上创建一个“观察者”,这几乎就是你想要的。您可以在GitHub 上找到该代码。具体看com.allanbank.mongodb.demo.coordination包中的代码。
HTH,罗伯
如果您的 _id 是 ObjectId 类型,您实际上可以使用时间戳:
prefix = Math.floor((new Date( 2013 , 03 , 11 )).getTime()/1000).toString(16)
db.foo.find( { _id : { $gt : new ObjectId( prefix + "0000000000000000" ) } } )
这样,事件源在哪里或何时发生都无关紧要,只在记录文档插入时才重要(高于上一个计时器)
当然,它是无模式的,您始终可以将 isNew 等字段设置为 true,并结合您的查询/游标将其设置为 false