Массовая строка базы данных в очередь сообщений для длительной работы - PullRequest
2 голосов
/ 08 января 2010

В запланированное время (на основе бизнес-правил) нам нужно от 10 000 до 200 000 строк в базе данных для обработки длительной операцией. Каждая строка должна обрабатываться индивидуально (они не зависят друг от друга), и это нормально, если это происходит асинхронно. Успешное завершение операции должно быть задокументировано (возможно, в базе данных).

Я полагаю, что лучший способ сделать это - использовать очередь сообщений, чтобы она была долговечной и могла легко масштабироваться. Во-первых, это лучшее решение? Если это так, каков наиболее эффективный способ поместить все строки из базы данных в очередь, гарантируя, что все строки перешли в очередь?

Примечание: мы - команда .Net, использующая C # 3.5, WCF, MSMQ и SQL 2005. Я исследовал NServiceBus и хотел бы использовать это, если рекомендуется.

Меня беспокоит, что база данных является узким местом (обновляя каждую строку, чтобы пометить как обработанную). Я также не знаю, как «транзакционно отправить» сообщение.

  1. Как мне «транзакционно отправить» сообщение? Под этим я подразумеваю следующее: загрузить строку из базы данных, отправить сообщение, обновить строку в базе данных. Если обновление не удалось, я не хочу, чтобы сообщение отправлялось.
  2. Это обычный сценарий или я должен делать это по-другому?
  3. Меня беспокоит то, что обновление отдельных строк в БД вызовет узкое место. Могу ли я "транзакционно отправить" партию сообщений, а затем пакетное обновление БД?

Ответы [ 2 ]

2 голосов
/ 08 января 2010

NServiceBus значительно упростит процесс настройки очередей. Это (схема msmq) является распространенным шаблоном для этой операции, но это не единственный вариант.

Вы также можете посмотреть SQL Server Service Broker и многие другие подобные технологии, чтобы сделать то же самое.

Есть несколько предостережений, о которых вы должны знать с MSMQ:

  1. Транзакционные очереди не могут быть сбалансированными по нагрузке, если они не являются очередью домена Active Directory. Большой вывод здесь заключается в том, что очередь должна находиться на одной машине, что означает, что она может быть потеряна, если машина потеряна (постоянная или временная). Это не большая проблема, но стоит принять к сведению
  2. Очереди MSMQ имеют два «режима» транзакционного и нетранзакционного. Только транзакционные очереди гарантируют доставку сообщений.
  3. Сообщения MSMQ сами по себе ограничены 4 МБ (или около того), и вы должны сами управлять сериализацией (хотя сериализация .NET по умолчанию довольно проста с сериализатором XML). Если вы хотите, чтобы сообщения размером более 4 МБ, вам нужно либо управлять ими вне очереди, либо управлять несколькими сообщениями в очереди самостоятельно (BizTalk имеет способ сделать это, так что это не большая проблема). 4 МБ должно быть достаточно большим для ваших нужд.
  4. Как только вы «принимаете» сообщение из очереди, оно немедленно удаляется, поэтому в зависимости от вашего дизайна это может быть проблемой. будет иметь возможность для ваших потребителей "принять" сообщение, потерпеть неудачу и сделать так, чтобы сообщение не вернулось в очередь.

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

Наконец, в качестве альтернативы вашему текущему предложению (и вам есть с чем сравнивать) вы можете реализовать описанный сценарий непосредственно из БД. Как набросок салфетки:

  1. Процесс запускается в БД и заполняет таблицу «ожидающими» строками строк, присваивая каждому уникальный идентификатор (guid и т. Д.)
  2. Создайте SP, который возвращает "n" этих строк вызывающей стороне, и помечает те же строки как "ожидающие" в БД. Если строк нет, возвращается 0 или -1, или что-то еще
  3. Создание SP, который получает список идентификаторов строк и расположение (информацию о завершении) для задания и обновляет таблицу ожидания, либо помечая их как выполненные, либо удаляя их, и регистрируя данные о завершении
  4. Ваши клиенты звонят в первый SP и запрашивают набор строк для работы на
  5. Ваши потребители обрабатывают строки
  6. Ваши потребители звонят второму ИП, чтобы записать проделанную работу

Затем вы можете периодически запускать отчеты, чтобы увидеть, какая работа была выполнена и все еще ожидает, и, если необходимо, изменить строки с ожидающих на ожидание и т. Д. Это будет иметь примерно такое же масштабирование, как и у вашего другого решения, удалить слой косвенности (который может быть плохо, в зависимости от) и обеспечить немного более линейный процесс. По сути, этот процесс работает так, как работает Service Broker (конечно, очень перегнано).

Все зависит от того, как вам удобнее всего это реализовывать. Я сделал это обоими способами, и у обоих есть свои плюсы и минусы.

2 голосов
/ 08 января 2010

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

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

Вы хотите самый простой способ, которым вы можете сделать следующее.

  1. Создать очередь.

  2. Создайте несколько пользовательских процессов, которые все читают из очереди.

  3. Начать процесс производства. Это выполнит ваш запрос и напишет очередь, выполняя как можно меньше в процессе.

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

Когда запрос пуст, вы должны закрыть все. Трудно (но не невозможно) закрыть потребителей. Распространено специальное сообщение «все готово», которое вы помещаете в очередь после запроса. Если у вас есть n потребителей, вы помещаете n копий этого готового к работе в очередь, чтобы все потребители могли полностью отключиться.

Обратите внимание, что это очень похоже на конвейер Unix. По очень веской причине.


Редактировать.

  1. Как мне «транзакционно отправить» сообщение? Под этим я подразумеваю следующее: загрузить строку из базы данных, отправить сообщение, обновить строку в базе данных. Если обновление не удалось, я не хочу, чтобы сообщение отправлялось.

    Не делай этого. Это беспорядок. Ваш производитель отправляет сообщения. Сама очередь совершенно надежна. Сообщения не «теряются» или «как-то» не обрабатываются. Очередь может быть настроена для работы с файловой системой, чтобы сообщения оставались постоянными до их использования.

    Потребители могут пометить вещи как «выполненные», когда они с ними покончили. Это сильно замедлит ход событий.

    Если вы хотите сохранить статус «обработки», используйте технику хранилища данных и не сохраняйте ее с вашими транзакционными данными.

  2. Да, это распространенный сценарий. Каждый пытается сделать слишком много на стороне продюсера такого рода вещей. Вам редко требуется вся «транзакционная» обработка, которую вы считаете нужной. Вы должны детализировать требования конечного пользователя для этого. Вам действительно нужно это обновление? Или это просто потому, что, кажется, вам нужно где-то записывать статус обработки?

    Помните, очереди очень надежны. Не изобретайте постоянную очередь в базе данных.

    Считайте http://www.microsoft.com/windowsserver2003/techinfo/overview/msmqfaq.mspx в «Транзакционных сообщениях». У вас есть много вариантов конфигурации, чтобы гарантировать, что сообщение попадает в очередь.

  3. Меня беспокоит то, что обновление отдельных строк в БД вызовет узкое место.

    Хорошо подумать. Так что не делай этого. Вопрос в обновлениях базы данных всегда "почему?" Если это «для полноты», то это вовсе не причина. Если это «для восстановления» или «для предотвращения повторной обработки», вы можете подумать о лучшем дизайне.

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

Самая простая очередь - лучшая. Вам редко нужно много транзакционного смешного бизнеса. Просто поставьте в очередь сообщения и выполняйте работу на стороне потребителя.

...