Я использую NodeJS с Express для создания простого api отдыха. Мой рабочий процесс:
Мой код для сохранения такой:
await collection.updateOne({
// match all the properties
}, {
$inc: {
'encountered': 1
}
}, {
upsert: true,
});
Однако это создает состояние гонки, если я сделаю несколько одновременных вызовов одновременно ... Например, если я сделаю запрос POST 5 раз одновременно, я могу получить два результата:
один раз встречалось: 3x второй раз встретилось: 2x
Я предполагаю, что первая вставка провела поиск в БД, не нашла элемент и была подготовлена для вставки, в то время как вторая вставка получила время потока, не нашла элемента и также была подготовлена для вставки. Затем срабатывала первая вставка, увеличивалась несколько раз, а затем срабатывала вторая вставка и увеличивалась несколько раз.
Как мне с этим справиться? Глобальная переменная пытается имитировать синглтон ..? Я все еще не уверен, что это будет потокобезопасно ... Я не против худшей производительности, но мне нужно, чтобы записи в БД были абсолютно поточно-безопасными / атомарными, т.е. поиск и обновление считались атомарной операцией.
Обновлено: в качестве альтернативы я был бы рад не принимать никаких вызовов POST (т.е. блокировать операцию POST), пока мой предыдущий вызов не был полностью разрешен ..? Я не уверен, как правильно решить эту проблему с помощью NodeJS.
Edit2: Я также пробовал db.collection.createIndex, который затем не выполняет запись. Боюсь, что при повторной попытке этой неудачной записи я столкнусь с той же проблемой.
Вы просто предполагаете, что у вас может быть проблема с параллелизмом? Или вы действительно тестировали и определили проблему параллелизма?
@ jfriend00 Я протестировал все локально, и он отлично работает, но как только я запустил его в производство, где я могу получить даже 20-30 запросов одновременно, я увидел, что несколько идентичных элементов сохраняются в БД => Я пришел к вывод, что это проблема параллелизма, которая, как я ожидал, исходила из фона Java. Но поскольку в NodeJS нет «синхронизированного», я не знаю, как к этому подойти.
Хорошо, тогда ищите места, где вы неправильно используете встроенные функции параллелизма в mongodb, вместо того, чтобы пытаться создать свой собственный элемент управления параллелизмом поверх БД. Вы должны позволить базе данных управлять этим за вас.





upsertдолжен быть атомарным - в этом смысл его использования вместо отдельного поиска и вставки. Итак, пока выполняется первый запрос, на эту коллекцию на мгновение накладывается блокировка до тех пор, пока запись не будет обновлена или вставлена. Это работа базы данных, а не ваша, блокируя запросы. Если вы используете соответствующие функции в базе данных, база данных должна справиться с этим за вас. Я вообще не эксперт по параллелизму mongodb, но я думаю, что весь смысл$incиupsertзаключается именно в том, чтобы решить эту проблему параллелизма внутри базы данных, поэтому вам не нужно.