Получение части работы - PullRequest
0 голосов
/ 11 июня 2009

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

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

Ответы [ 4 ]

1 голос
/ 11 июня 2009

Существует несколько подходов - вы можете связать каждый процессор токеном и иметь SPROC, который устанавливает этот токен в отношении следующих [n] доступных элементов; возможно что-то вроде:

(примечание - необходим подходящий уровень изоляции; возможно, сериализуемый: SET TRANSACTION ISOLATION LEVEL SERIALIZABLE)

(отредактировано для исправления TSQL)

UPDATE TOP (1000) WORK
SET [Owner] = @processor, Expiry = @expiry
OUTPUT INSERTED.Id -- etc
WHERE [Owner] IS NULL

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

0 голосов
/ 11 июня 2009

Весьма похоже на этот вопрос: Состояние гонки очереди процесса SQL Server

Вы запускаете запрос, чтобы назначить 100 строк данному процессору. Если вы используете эти подсказки блокировки, то это «безопасно» в смысле параллелизма. И это один оператор SQL без операторов SET.

Это взято из другого вопроса:

UPDATE TOP (100)
    foo
SET
    ProcessorID = @PROCID
FROM
    OrderTable foo WITH (ROWLOCK, READPAST, UPDLOCK)
WHERE
    ProcessorID = 0    --Or whatever unassigned is
0 голосов
/ 11 июня 2009

Вы не сказали, какой сервер базы данных используете, но есть несколько вариантов.

MySQL включает расширение INSERT для SQL99, чтобы ограничить количество обновляемых строк. Вы можете назначить каждому работнику уникальный токен, обновить количество строк, а затем выполнить запрос, чтобы получить пакет этого работника. Марк использовал синтаксис UPDATE TOP, но не указал сервер базы данных.

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

0 голосов
/ 11 июня 2009

У вас может быть специальная таблица для обработки очереди, в которой потребители удаляют (или помечают) работу как обрабатываемую, или используют решение организации промежуточного программного обеспечения, такое как MSMQ или ActiveMQ.

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

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

Вопросы, связанные с очередями таблиц SQL:

Очередь с использованием таблицы

Обработка SQL для запроса таблицы очередей с приоритетом

Смежные вопросы по промежуточному программному обеспечению:

Создание высокопроизводительной очереди с автоматическим резервным копированием

Платформа обмена сообщениями

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