Является ли перемещение документов между коллекциями хорошим способом представления изменений состояния в MongoDB? - PullRequest
15 голосов
/ 10 мая 2011

У меня есть две коллекции: одна ( A ), содержащая элементы для обработки (относительно небольшие), и одна ( B ) с уже обработанными (довольно большими, с дополнительными полями результатов). ).

Элементы считываются из A , обрабатываются и сохраняются () 'd в B , затем удаляются ()' d из A .

Обоснование состоит в том, что индексы могут быть разными по всем этим, и что "поступающая" коллекция может таким образом сохраняться очень маленькой и быстрой.

Я столкнулся с двумя проблемами:

  • если время удаления () или save () истекло или произошла ошибка при загрузке, я полностью теряю элемент или обрабатываю его дважды
  • если оба сбоя, побочные эффекты случаются, но записи об этом нет

Я могу обойти случай двойного сбоя с помощью блокировок findAndModify (в противном случае нет необходимости, у нас есть блокировка на уровне процесса), но тогда у нас возникнут проблемы с устаревшей блокировкой, и частичные сбои все еще могут возникать. Насколько я могу судить, нет способа атомарно удалить + сохранить в разных коллекциях (может быть, по замыслу?)

Есть ли передовая практика для этой ситуации?

Ответы [ 2 ]

6 голосов
/ 10 мая 2011

Нет способа атомарно удалить + сохранить в разных коллекциях, насколько я могу судить (может быть, по замыслу?)

Да, это по замыслу. MongoDB явно не предоставляет соединения или транзакции. Удалить + Сохранить - это форма транзакции.

Есть ли передовая практика для этой ситуации?

У вас действительно есть два варианта низкой сложности, оба включают findAndModify.

Вариант № 1: одна коллекция

Исходя из вашего описания, вы в основном строите очередь с некоторыми дополнительными функциями. Если вы используете одну коллекцию, вы используете findAndModify для обновления статуса каждого элемента в процессе его обработки.

К сожалению, это означает, что вы потеряете это: ... что «входящая» коллекция может быть очень маленькой и быстрой, таким образом .

Вариант № 2: две коллекции

Другой вариант - это двухфазный коммит, использующий findAndModify.

Посмотрите документы для этого здесь .

После обработки элемента в A вы устанавливаете поле, чтобы пометить его для удаления. Затем вы копируете этот предмет в B . После копирования в B вы можете удалить элемент из A .

2 голосов
/ 10 мая 2011

Я сам еще не пробовал, но в новой книге 50 советов и рекомендаций для разработчиков MongoDB несколько раз упоминается об использовании заданий cron (или services / scheduler) для очистки подобных данных. Вы можете оставить документы в Коллекции А помеченными для удаления и выполнять ежедневные задания для их очистки, уменьшая общий объем исходной транзакции.

Из того, что я узнал до сих пор, я никогда не оставляю базу данных в состоянии, в котором я полагаюсь на следующее действие базы данных, выполняющееся успешно, если только это не действие last (ведение журнала пересылает последний дБ действие по восстановлению). Например, у меня есть трехфазный процесс регистрации учетной записи, где я создаю пользователя в CollectionA, а затем добавляю другой связанный документ в CollectionB. Когда я создаю пользователя, я встраиваю детали документа CollectionB в CollectionA на случай, если вторая запись не удалась. Позже я напишу процесс, который удаляет встроенные данные из CollectionA, если документ в CollectionB существует

Отсутствие транзакций вызывает болевые точки, подобные этой, но я думаю, что в некоторых случаях появляются новые способы мышления об этом. В моем случае время покажет, как я продвигаюсь с моим приложением

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...