Проблема параллелизма с очередью базы данных, требуется переносимое решение - PullRequest
1 голос
/ 05 апреля 2011

У меня есть очередь входящих сообщений, реализованная в базе данных SQL (в настоящее время MS SQL Server), доступной через веб-сервис. Этот веб-сервис запускает устаревший протокол, который мы не можем контролировать, и должен возвращать либо ответ «нет сообщений в очереди», либо оба:

  • Сведения о самом старом сообщении в очереди
  • Количество других сообщений в очереди

Алгоритм, используемый для этого, в настоящее время очень груб:

  1. Выбрать все сообщения в очереди
  2. Количество оставшихся сообщений = количество строк - 1
  3. Обновить самое старое сообщение, чтобы установить флаг сбора

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

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

У кого-нибудь есть яркие идеи?

Спасибо!

Ответы [ 2 ]

2 голосов
/ 05 апреля 2011

Поскольку вы уже используете SQL-сервер, вам следует рассмотреть возможность использования SQL Server Service Broker .

Однако это связывает вас с SQL-сервером ...

Одна вещьвы могли бы подумать, что вы выбираете ... получаете идентификатор строки ... обновляете строку, чтобы пометить ее как собранную с новым идентификатором строки (guid или тому подобным), который вы сгенерировали ... выберите его снова ... еслиИдентификатор строки - это тот, который вы установили, тогда вы тот, кто получил его ... если не кто-то залез перед вами, и вы должны пойти и получить другого.

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

1 голос
/ 05 апреля 2011

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

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

Если бы это был я, я бы настроил хранимую процедуру (почему вы думаете, что они не переносимы?) С операциями в транзакции с сериализуемой блокировкой - я бы также кешировал число сообщений в очереди с помощью TTL основывается на количестве операций / возрасте кэшированного значения, чтобы уменьшить количество дорогостоящих совокупных операций в базовой таблице. Это может быть сделано путем одновременной выдачи DML-операции на языке управления, но общий эффект заключается в том, что операция займет значительно больше времени.

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

...