2010-01-08 3 views
0

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

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

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

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

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

ответ

2

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

+0

Зачем вообще закрывать потребителей? Процесс, как представляется, является периодическим, позволяет потребителям бездействовать и ждать большего количества данных в очереди. Если вы используете тайм-аут в RecieveMessage, вы можете периодически выходить из заблокированного состояния и проверять, получили ли они управляющее сообщение для выключения. – GrayWizardx

+0

@GrayWizardx: Хорошая точка. Мы Linux, и закрытие источника во главе конвейера распространяет простой EOF на потребителей, и все это прекрасно закрывается. Я проецировал эту операцию закрытия. Если это не нужно, сохраните сложность. –

+0

Спасибо, это тоже отличная информация.Если бы кто-то из вас мог помочь с моими дальнейшими моментами, это было бы здорово. Меня беспокоит узкое место в db и как отправлять транзакции по транзакциям. – JontyMC

2

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

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

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

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

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

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

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

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

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

+0

Спасибо, это отличная информация. Я обновил вопрос, чтобы уточнить мои проблемы. – JontyMC

Смежные вопросы