【问题标题】:MongoDB (+ Node/Mongoose): How to track processed records without "marking" all of them?MongoDB(+ Node/Mongoose):如何在不“标记”所有记录的情况下跟踪处理过的记录?
【发布时间】:2019-10-20 06:34:43
【问题描述】:

我有几个大型“原始”文档集合,它们在队列中处理,处理后的结果全部放入一个集合中。

队列仅在系统没有其他问题时运行,并且新数据一直被添加到“原始”集合中。

我需要做的是确保队列知道它已经处理了哪些文档,因此它不会 (a) 多次处理任何文档,或 (b) 跳过文档。使用“已处理”标志更新每个原始记录并不是一个好的选择,因为它会增加太多开销。

我正在使用带有 NodeJS 和 Mongoose 的 MongoDB 4.x。 (我不需要一个严格由猫鼬驱动的答案,但一个就可以了)。

我最初的尝试是通过检索按_id 排序的小批量(比如 100)原始文档,然后在返回结果中获取第一个和最后一个 _id 值,并存储这些值,所以当我准备好处理下一批时,我可以将find({}) 查询限制为_id 大于我作为最后处理结果存储的记录。

但是再仔细研究一下,除非我误解了什么,看来我真的不能指望_id 的严格排序。

我已经研究了实现自动递增数字 ID 字段(SQL 样式)的方法,该字段具有严格的顺序,但我看到的解决方案看起来像是添加了一个重要的每次创建记录时都会产生大量开销(与标记已处理记录所需的开销没有什么不同,只是在插入端而不是处理端),并且该系统需要非常快速地处理大量记录。

有什么想法吗?有没有办法做一个超级高效的自动递增数字 ID?默认_id 属性在这种情况下实际上是否有效,我误解了?还有其他方法吗?

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    根据ObjectID的文档:

    虽然 ObjectId 值应随时间增加,但它们不会 必然单调。这是因为他们:

    • 仅包含一秒的时间分辨率,因此在同一秒内创建的 ObjectId 值没有保证顺序,并且
    • 由客户端生成,可能具有不同的系统时钟。

    因此,如果您每秒创建那么多记录,那么 _id 排序不适合您。

    但是,mongo 实例中的Timestamp保证是唯一的

    BSON 有一个特殊的时间戳类型供内部 MongoDB 使用,而不是 与常规日期类型相关联。时间戳值是 64 位 价值在哪里:

    前 32 位是 time_t 值(自 Unix 纪元以来的秒数) 第二个 32 位是一个递增序数 给第二个。

    在单个 mongod 实例中,时间戳值始终是唯一的。

    虽然它明确指出这是针对internal use 的,但您可能需要考虑一下。假设您正在处理单个 mongod 实例,您可以在记录进入带有时间戳的“原始”集合时装饰您的记录......然后您可以只记住最后处理的记录。您的队列只会选择时间戳大于上次处理的时间戳的记录。

    【讨论】:

    • 一直在用这个方法测试,目前看来效果不错。
    猜你喜欢
    • 2014-06-10
    • 1970-01-01
    • 2012-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-26
    相关资源
    最近更新 更多