MongoDB 2.6 的 Bulk API


由于有批量操作的需求,看了一下这个 Bulk API,看完之后有几个问题。

当前为了实现 bulk insert,我自己定义了一个 List, 每次有新数据要插入的时候,将数据转换成合适的格式,放进这个 List 里,等需要的时候执行 insert(List) 操作。这相当于我自己维护了一个缓存队列,而且这种队列还需要考虑到线程安全。从 Bulk.insert() API 来看,只是把数据直接 insert 到这个 bulk 里。

我想问的是:

  1. Bulk 是不是自己在客户端维护了一个缓存队列?如果是的话,它的线程安全性有保障吗?
  2. 有了 Bulk 之后,是不是我不需要自己去维护我的缓存队列,交给 Bulk 去做就可以了?
  3. Bulk 是用 db.collection.initializeOrderedBulkOp() 方法获得的。测试了一下发现,我似乎必须得长期持有这个方法返回的引用,否则无法用其他方法再重新获得缓存队列中的数据。那么,如果长期持有的话,是不是在 execute() 之前会保持着一个长连接?那如果连接断掉呢?

java 多线程 mongodb

CtrlZ 10 years, 4 months ago

这个取决于驱动的实现。mongodb的API并不规定这个线程安全性(如Javascript驱动就没有线程)。从你的描述中估计你用的是Java。在Java驱动里面 Bulk API用的是ArrayList所以理论上线程安全没有保障。不过你在调用的一般就是insert(),相当于 ArrayList.add(),实际使用中多线程同时调用add()并没有太多问题。

如果安全一点的话,就像你所做的一样,使用一个线程安全List,自己来维护这个队列,最后一次性交给MongoDB驱动来execute。

关于第3个问题,这个和连接没有直接的关系。bulk操作可以使用一个,也可以对不同操作使用连接池内的不同连接(bulk操作内部会对所有操作按类型进行分组,每个组都是自己的一个网络请求)。不一定是一个长连接。如果连接断掉,对于orderedBulkOp 这个bulk操作就会失败并终止;对于unorderedBulkOp,会忽略错误并继续剩下的操作。

另外, 上述讨论针对于2.6。 2.4或以前会有所不同。

暧昧的三厘米 answered 10 years, 3 months ago

Your Answer