mongodb upsert не обновляется, если заблокирован

У меня есть приложение, написанное на C ++ с 16 потоками, которое читает из вывода wireshark / tshark. Wireshark / tshark анализирует файлы pcap, которые являются захватами сигналов gsm_map.

Mongodb составляет 2.6,7

Структура, которая мне нужна для моих документов, выглядит следующим образом:

Обратите внимание, что «пакет» является массивом, станет понятно почему позже.

Для всех, кто не знает TCAP, уровень TCAP ориентирован на транзакции, это означает, что все пакеты включают в себя:

  • Состояние транзакции: начало / продолжение / конец
  • Идентификатор исходной транзакции (otid)
  • ID целевой транзакции (dtid)

Так, например, вы можете увидеть транзакцию, состоящую из 3-х пакетов, которая на уровне TCAP выглядит примерно так:

Два пакета, один «начало», один «конец».

{
"_id" : ObjectId("54ccd186b8ea19c89ee8f231"),
"deleted" : "0",
"packet" : {
"datetime" : ISODate("2015-01-31T12:58:11.939Z"),
"signallingType" : "M2PA",
"opc" : "326",
"dpc" : "6406",
"transState" : "begin",
"otid" : "M2PA0400435B",
"dtid" : "",
"sccpCalling" : "523332075100",
"sccpCalled" : "523331466304",
"operation" : "mo-forwardSM (46)",
...
}
}

/* 1 */
{
"_id" : ObjectId("54ccd1a1b8ea19c89ee8f7c5"),
"deleted" : "0",
"packet" : {
"datetime" : ISODate("2015-01-31T12:58:16.788Z"),
"signallingType" : "M2PA",
"opc" : "6407",
"dpc" : "326",
"transState" : "end",
"otid" : "",
"dtid" : "M2PA0400435B",
"sccpCalling" : "523331466304",
"sccpCalled" : "523332075100",
"operation" : "Not Found",
...
}
}

Из-за сетевой архитектуры мы отслеживаем две (2) точки, и трафик сбалансирован между этими двумя точками. Это означает, что иногда мы видим «продолжить» или «закончить» ДО «начала». И наоборот, мы можем увидеть «продолжить» ДО «начала» или «конца». Короче говоря, транзакции не приказал.

Более того, несколько конечных точек «разговаривают» между собой, и идентификаторы транзакции могут дублироваться, 2 конечные точки могут использовать один и тот же tid и две другие конечные точки одновременно, хотя это происходит не всегда, делает бывает.

Из-за более позднего мне также нужно использовать глобальные заголовки (например, номера телефонов) уровня «вызов» и «вызов» уровня SCCP.

Имейте в виду, что я не знаю, в каком направлении движется данный пакет, вот что я делаю:

  • Всякий раз, когда я получаю новый пакет, я должен выяснить, существует ли уже транзакция в mongodb, я использую upsert для этого.
    • Я делаю это путем поиска текущего пакета otid или dtid в otid или dtid существующих пакетов
    • Если это так: вставьте новый пакет в существующий документ.
    • Если это не так: создайте новый документ с пакетом.

Например, это упор для «конца», который должен найти «начало»:

db.runCommand(
{
update: "packets",
updates:
[
{ q:
{ $and:
[
{
$or: [
{ "packet.otid":
{ $in: [ "M2PA042e3918" ] }
},
{ "packet.dtid":
{ $in: [ "M2PA042e3918" ] }
}
]
},
{
$or: [
{ "packet.sccpCalling":
{ $in: [ "523332075151", "523331466305" ] }
},
{ "packet.sccpCalled":
{ $in: [ "523332075151", "523331466305" ] }
}
]
}
]
},
{
$setOnInsert: {
"unique-id": "422984b6-6688-4782-9ba1-852a9fc6db3b", deleted: "0"},
$push: {
packet: {
datetime: new Date(1422371239182),
opc: "327", dpc: "6407",
transState: "end",
otid: "", dtid: "M2PA042e3918", sccpCalling: "523332075151", ...  }
}
},
upsert: true
}
],
writeConcern: { j: "1" }
}
)

Теперь все это работает, пока я не запустил его в производство.

Кажется, пакеты быстро набирают скорость, и я вижу много:

Предупреждения «ClientCursor :: staticYield не может разблокировать B / C рекурсивной блокировки»
Я читал, что мы можем проигнорировать это предупреждение, но я обнаружил, что мои возражения НЕ обновляют документы! Похоже, что есть замок и mongodb забывает об обновлении. Если я изменю upsert на простую вставку, никакие пакеты не будут потеряны

Я также читал, что это связано с отсутствием используемых индексов, у меня есть следующий индекс:

"3" : {
"v" : 1,
"key" : {
"packet.otid" : 1,
"packet.dtid" : 1,
"packet.sccpCalling" : 1,
"packet.sccpCalled" : 1
},
"name" : "packet.otid_1_packet.dtid_1_packet.sccpCalling_1_packet.sccpCalled_1",
"ns" : "tracer.packets"

Итак, в заключение:

1.- Если этот индекс не верен, может кто-нибудь помочь мне создать правильный индекс?
2.- Это нормально, что Монго НЕ будет обновлять документ, если обнаружит блокировку?

Спасибо и всего наилучшего!

Дэвид

1

Решение

Почему вы храните все пакеты в массиве? Обычно в такой ситуации лучше сделать каждый пакет отдельным документом; Трудно сказать больше без дополнительной информации о вашем случае использования (или, возможно, большего знания всех этих акронимов, которые вы используете: D). Ваши обновления станут вставками, и вам не нужно будет делать запрос на обновление. Вместо этого некоторые другие метаданные пакета могут объединять связанные пакеты, чтобы вы могли реконструировать транзакцию или все, что вам нужно сделать.

Для более непосредственного решения вашего вопроса я бы использовал поле массива tids хранить [otid, dtid] и поле массива sccps хранить [sccpCalling, sccpCalled]что бы ваш запрос на обновление выглядел как

{ "tids" : { "$in" : ["M2PA042e3918"] }, "sccps" : { "$in" : [ "523332075151", "523331466305" ] } }

и поддается индексу { "tids" : 1, "sccps" : 1 },

0

Другие решения


По вопросам рекламы [email protected]