Mongo db写入顺序

时间:2019-07-12 11:35:37

标签: javascript mongodb

如果您是一名蒙哥神,无论如何想帮助我,这篇文章将非常长,我衷心感谢您。对于收集到的所有数据,我会尽量讲究。

我在MongoDD数据库中遇到一些奇怪的行为,并且我在质疑mongodb的写入顺序。

我记录了一些错误,这些错误只在执行时发生,这使我认为这里存在一个计时问题,但是请求是如此缓慢,以至于我不明白在糟糕的情况下它会如何发生

起点:

  • 所有ObjectIds都是mongo自动提供的,我从来没有将它们放在我的身边
  • 此objectId被索引(显然)且唯一
  • 我通过以下请求在这些请求ID中使用时间戳查询数据库:
    db.getCollection('eventStore').find({
      '_id': {
        '$gt': ObjectId("5d285c784460c502cc66ff9b"),
        '$lte': ObjectId("5d285cf7856cda0266215c77")
      }
    })
  • 然后使用基本的Node.js客户端可能性流式传输此请求的结果:
    collection.find({
        '_id': {
          ...(lower ? { '$gt': lower } : {}),
          '$lte': higher
        }
      }).sort({ _id: 1 }).stream({
        transform: (element) => {
          logger.info(`Exiting Get events by range::${JSON.stringify(lower)}::${JSON.stringify(higher)}`)
          logger.info(`Parse event::${JSON.stringify(element)}}`)
          return // PARSED EVENT
        }
      })
  • 在这一点上,我知道.sort({ _id: 1 })可能没有用,但是我还是把它放在这里,以防万一。
  • 请求过程非常慢:我先查询上限,以获取eventStore的偏移量,然后查询视图的偏移量,然后查询商店,以获取这些边界之间的所有事件。
  • mongo数据示例:
    /* 1 */
    {
        "_id" : ObjectId("5d285cf77f6482027108c15c"),
        "events" : [ 
            // Some events
        ]
    }

    /* 2 */
    {
        "_id" : ObjectId("5d285cf77f6482027108c15d"),
        "events" : [
            // Some events
        ]
    }

    /* 3 */
    {
        "_id" : ObjectId("5d285cf7856cda0266215c77"),
        "events" : [ 
            // Some events
        ]
    }

预期的Mongo行为:

  • Mongo正在自动分配ID,所以我希望当ID ObjectId(“ 5d285cf7856cda0266215c77”)存储在基本数据库中,所有带有较早时间戳记的ID都已安全存储在基本数据库中。 ==>无后退
  • 在ObjectId中编码的时间戳记(由mongo自行给出)是在将其写入并持久存储在数据库中时使用的时间戳,而不是在Mongo接收时使用的时间戳。

实际行为(在记录器的功能中记录):

  • 在记录器的功能中仅能看到第一个和最后一个_ids
    {"message":"Exiting Get events by range::\"5d285c784460c502cc66ff9b\"::\"5d285cf7856cda0266215c77\"","level":"info","timestamp":"2019-07-12 10:12:07"} 
    {"message":"Parse event::{\"_id\":\"5d285cf77f6482027108c15c\",\"events\":[ // Data ]}}","level":"info","timestamp":"2019-07-12 10:12:07"} 
    {"message":"Exiting Get events by range::\"5d285c784460c502cc66ff9b\"::\"5d285cf7856cda0266215c77\"","level":"info","timestamp":"2019-07-12 10:12:07"} 
    {"message":"Parse event::{\"_id\":\"5d285cf7856cda0266215c77\",\"events\":[ // Data ]}}","level":"info","timestamp":"2019-07-12 10:12:07"}

  • 似乎:
    1. 或者在调用时事件_id:ObjectId(“ 5d285cf77f6482027108c15d”)不在基础中,但是较旧的_id:ObjectId(“ 5d285cf7856cda0266215c77”)在此基础上。
    2. 或者我的请求或流在通话时无效(但现在返回正确的答案)
    3. 还有什么?

1 个答案:

答案 0 :(得分:1)

  

Mongo正在自动分配ID,因此我希望将ID ObjectId(“ 5d285cf7856cda0266215c77”)存储在基准库中时,所有带有较早时间戳记的ID都已安全地存储在基准库中。 ==>无后退

Mongo _idsObjectIds,它们是:

  
      
  • 一个4字节的值,表示自Unix时代以来的秒数,
  •   
  • 5个字节的随机值,并且
  •   
  • 3字节计数器,以随机值开头。
  •   

这些通常是通过应用程序驱动程序代码生成的(在将数据发送到mongo的服务器上)。

这意味着:

  1. 网络延迟会创建乱序记录
  2. 具有时钟漂移的应用服务器可以创建乱序记录
  3. 5个字节的随机值不一定在同一秒内向前移动(即使mongo分配了_id,它也会创建乱序记录)
  4. NTP更新可以创建乱序记录(甚至在mongo上-更新时钟时也不会产生任何拖尾现象)
  5. Le秒可以创建乱序记录

如果您查看共享的_id,则5d285cf77f6482027108c15d5d285cf7856cda0266215c775d285cf7)的前4个字节(8个字符)都共享相同的时间戳,因为它们发生了在时代之后的同一秒内。