MongoDB - 反映广告订单

时间:2016-08-02 12:28:36

标签: mongodb

我有一个不断将文档插入MongoDB集合的应用程序。

我正在寻找一种在插入订单后查询文档的方法。

我想要使用的候选人:

  • _id字段
  • 创建日期字段
  • 序列号(自动增量)

正如文档所说,_id字段不是一个好的候选字段。创建日期字段可能是一个很好的候选者,但是时钟可能不同步这一事实可能会破坏顺序。关于序列号,文档提出了两种方法:计数器和乐观循环。计数器方法不保证插入顺序,因为即使D1,也可以在另一个文档D2之后插入文档D1.seq < D2.seq。例如,如果D1占用序号5,则D2占用序列号6,然后插入D2,然后插入D1。在插入环境较重的情况下,乐观循环方法很疯狂。

还有其他方法吗?

修改

使用计数器的方法存在问题。请考虑以下情形。我有一个应用程序A,它不断地将文档插入到集合中。我还有另一个应用程序B,它不断轮询来自同一集合的文档。应用程序A是多线程的。两个帖子T1T2即将分别插入文档D1D2。在插入过程中,应用程序B要求提供更多文档。假设以下操作顺序:

  1. 线程A-T1占用下一个序列号N
  2. 线程A-T2占用下一个序列号N+1
  3. 线程A-T2插入D2
  4. 应用B要求包含seq >= N的文档(假设处理的最后一个文档的序号为N-1)并收到D2D1尚未插入)
  5. 线程A-T1插入D1
  6. 应用B要求提供seq >= N+2的文档(因为上次处理的文档的序号为N+1
  7. 在这种情况下,永远不会处理D1

1 个答案:

答案 0 :(得分:0)

如果您希望每秒数十个插入,乐观锁是唯一的方法。

否则时钟同步可能是个更好的主意。

考虑到计数器,如果在D1之后保留D2,您是否可以详细说明它对您的应用程序的影响,因为您保证获取序列号的顺序? &#34;插入&#34; mongodb本身的操作有多个阶段,你可以像依赖日记一样深入。

修改

您会将tailable cursor视为申请B的选项吗?它没有直接回答这个问题,但它可以解决问题背后的问题。

编辑2

然后,您可能需要使用任何类型的消息队列在应用程序之间进行通信,例如在图像上。这可能是一种矫枉过正,但如果您确定乐观锁定是一个瓶颈,那么它可能是可以接受的。

在下图中:

  1. 应用程序A以任意顺序插入文档,并从mongo客户端检索唯一对象ID。

  2. 应用程序A以任意顺序将objectID发送到队列

  3. 应用程序B从队列中获取下一个objectID

  4. 应用程序B按ID从数据库中获取文档

  5. enter image description here

    编辑3

    最后,您可以考虑向文档添加状态并将乐观锁转换为应用B

    1. 检索未处理文档的对象ID:db.collection.findOne({status: null}, {})

    2. 将其状态更改为&#39;处理&#39;

      db.collection.findAndModify({
          query: { _id: objectId, status: null }, 
          update: { $set: { status: 'processing' }}
      })
      

      如果它返回null - 文档正由另一个B实例处理,所以返回步骤1

    3. 处理文档并将其状态更新为“完成”

      db.collection.findAndModify({
          query: { _id: objectId, status: 'processing' }, 
          update: { $set: { status: 'done' }}
      })
      
    4. 通过这种方法,您根本不关心确切的顺序。如果要按顺序处理文档,可以在ObjectId上添加时间戳或中继以在步骤1中对文档进行排序。它当然可能不是确切的顺序,但您并不需要它来保证所有文档都得到处理。