我使用 MongoDB 作为队列,使用 PHP-Queue 作为获取数据的一种方式。这是一个 POC,我在 OSX 机器上运行。我看到 Mongo 的性能非常缓慢,即 findmodify 函数。我在PHP端做了一堆测试,PHP处理只占5%左右的时间。当我用 10,000 条消息填充 Mongo 集合时,它会很快填充,大约 3-5 秒。但是当我清空它时,大约需要250 秒。这段时间只有大约 10 秒在 php 端。检查 mongod 进程,它从未超过 60MB,但 CPU 在整个时间内峰值超过 90%。我已经对集合进行了索引,下面是消息数据的示例以及索引。
示例消息(这是队列中 10,000 条类似消息之一):
{
"_id": ObjectId("526c47d5c5008c1d5cd63ef8"),
"payload": {
"0": {
"EVENT_HEADER_KEY": NumberInt(9094775),
"event_name": "Account Change",
"source_name": "Work",
"event_category_name": "Complex Events",
"EVENT_TIMESTAMP": "Aug 17 2013 12:00:00:000AM",
"PARENT_HEADER_KEY": null,
"year": NumberInt(2013),
"month": NumberInt(10),
"Company_Name": "ACME PRODUCTS, INC.",
"Company_Email": "blabla",
"Company_Phone": "555-555-5555",
"First_Name": "Jon",
"Last_Name": "Doe",
"ID_NUMBER": "111111111",
"created_by": "Load Job Name",
"created_at": "Oct 18 2013 04:07:31:140PM",
"product_analytical_category": "blabla",
"_Event_Type": "blabla",
"CUSTOMER_ID": "111111111"
}
},
"running": false,
"resetTimestamp": ISODate("2038-01-19T03:14:07.0Z"),
"earliestGet": ISODate("1970-01-01T00:00:00.0Z"),
"priority": 0,
"created": ISODate("2013-10-26T22:53:09.440Z")
}
这个集合的索引,似乎是自动创建的:
{
"_id": NumberInt(1)
}
检查 mongo.log,我可以看到当我清空队列时,每条消息只需要大约 1 毫秒,大约 70 条消息,然后 opid 会改变,然后会有 300-900 毫秒的延迟,然后继续新的 opid 以每条消息约 1 毫秒的相同速度。在 250 秒的处理时间中,这些 opid 更改约占 50-100 秒,因此还有更多工作要做。
摘自 mongo.log:
**Sat Oct 26 15:15:25.189** [conn4] warning: ClientCursor::yield can't unlock b/c of recursive lock ns: test.abe top: { **opid: 20064**, active: true, secs_running: 0, op: "query", ns: "test", query: { findandmodify: "abe", query: { running: false, earliestGet: { $lte: new Date(1382825725143) } }, update: { $set: { resetTimestamp: new Date(1382825785000), running: true } }, fields: { payload: 1 }, sort: { priority: 1, created: 1 } }, client: "127.0.0.1:53045", desc: "conn4", threadId: "0x119024000", connectionId: 4, locks: { ^: "w", ^test: "W" }, waitingForLock: false, numYields: 0, lockStats: { timeLockedMicros: {}, timeAcquiringMicros: { r: 0, w: 3 } } }
**Sat Oct 26 15:15:25.190** [conn4] warning: ClientCursor::yield can't unlock b/c of recursive lock ns: test.abe top: { **opid: 20064**, active: true, secs_running: 0, op: "query", ns: "test", query: { findandmodify: "abe", query: { running: false, earliestGet: { $lte: new Date(1382825725143) } }, update: { $set: { resetTimestamp: new Date(1382825785000), running: true } }, fields: { payload: 1 }, sort: { priority: 1, created: 1 } }, client: "127.0.0.1:53045", desc: "conn4", threadId: "0x119024000", connectionId: 4, locks: { ^: "w", ^test: "W" }, waitingForLock: false, numYields: 0, lockStats: { timeLockedMicros: {}, timeAcquiringMicros: { r: 0, w: 3 } } }
**Sat Oct 26 15:15:25.507** [conn4] warning: ClientCursor::yield can't unlock b/c of recursive lock ns: test.abe top: { **opid: 20141**, active: true, secs_running: 0, op: "query", ns: "test", query: { findandmodify: "abe", query: { running: false, earliestGet: { $lte: new Date(1382825725501) } }, update: { $set: { resetTimestamp: new Date(1382825785000), running: true } }, fields: { payload: 1 }, sort: { priority: 1, created: 1 } }, client: "127.0.0.1:53045", desc: "conn4", threadId: "0x119024000", connectionId: 4, locks: { ^: "w", ^test: "W" }, waitingForLock: false, numYields: 0, lockStats: { timeLockedMicros: {}, timeAcquiringMicros: { r: 0, w: 3 } } }
这在这 10,000 条消息的整个日志中基本相同。会有很长的 findandmodify() 序列,每条消息只需要 1 毫秒,然后 opid 会发生变化,并且会有一个延迟,可能需要将近一秒钟。我不知道这是否表明任何重要的事情,但我是 Mongo 的新手,我正在努力寻找任何看起来很有希望的模式。
更新:
该查询检查字段'running' 是否为假,它还检查earlyGet 字段是否比纪元(即1970 年1 月1 日)更新。我为这些字段添加了索引无济于事。由于这些字段对于集合中的所有消息(“假”和 1970 年 1 月 1 日)都是相同的,也许这就是为什么我对它们的索引只会增加查询时间的原因。我不知道我应该怎么做才能让它正常工作。它似乎应该抓取它发现的第一个比 1970 年 1 月 1 日更新的记录,但显然 Mongo 仍然遍历整个集合,这使得查询太慢而无法实用。此外,即使我没有选择标准,我仍然可以获得 202 秒的响应时间 - 更快,但仍然无法接受。我还看到那些“yield can't unlock b/c of recursive lock ns:”