Лучший способ использовать Таблицу базы данных в качестве очереди заданий (иначе обрабатывают в пакетном режиме очередь или очередь сообщений),

У меня есть таблица баз данных с ~50K строками в нем, каждая строка представляет задание, которое должно быть сделано. У меня есть программа, которая извлекает задание из DB, делает задание и откладывает результат в дб. (эта система работает прямо сейчас),

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

update tbl 
set owner = connection_id() 
where available and owner is null limit 1;

select stuff 
from tbl 
where owner = connection_id();

BTW; задачи рабочего могли бы отбросить там соединение между получением задания и представлением результатов. Кроме того, я не ожидаю, что DB даже близко подойдет к тому, чтобы быть горлышком бутылки, если я не испорчу ту часть (~5 заданий в минуту)

Есть ли какие-либо проблемы с этим? Существует ли лучший способ сделать это?

Примечание: "База данных как антишаблон IPC" незначительно кстати здесь потому что

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

16
задан marc_s 25 August 2019 в 08:22
поделиться

4 ответа

Вот то, что я использовал успешно в прошлом:

Схема таблицы MsgQueue

MsgId identity -- NOT NULL
MsgTypeCode varchar(20) -- NOT NULL  
SourceCode varchar(20)  -- process inserting the message -- NULLable  
State char(1) -- 'N'ew if queued, 'A'(ctive) if processing, 'C'ompleted, default 'N' -- NOT NULL 
CreateTime datetime -- default GETDATE() -- NOT NULL  
Msg varchar(255) -- NULLable  

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

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

Читатель вытягивает одно сообщение и изменяет состояние на "A" ctive, в то время как это работает над ним. То, когда это сделало это, изменяет состояние на "C" omplete. Это может удалить сообщение или не в зависимости от того, хотите ли Вы сохранить журнал аудита. Сообщения состояния = 'N' вытягивают в порядке MsgType/Timestamp, таким образом, существует индекс на MsgType + состояние + CreateTime.

Изменения:
Состояние для "E" rror.
Столбец для Читателя обрабатывает код.
Метки времени для изменений состояния.

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


Код из комментариев:

CREATE PROCEDURE GetMessage @MsgType VARCHAR(8) ) 
AS 
DECLARE @MsgId INT 

BEGIN TRAN 

SELECT TOP 1 @MsgId = MsgId 
FROM MsgQueue 
WHERE MessageType = @pMessageType AND State = 'N' 
ORDER BY CreateTime


IF @MsgId IS NOT NULL 
BEGIN 

UPDATE MsgQueue 
SET State = 'A' 
WHERE MsgId = @MsgId 

SELECT MsgId, Msg 
FROM MsgQueue 
WHERE MsgId = @MsgId  
END 
ELSE 
BEGIN 
SELECT MsgId = NULL, Msg = NULL 
END 

COMMIT TRAN
14
ответ дан 30 November 2019 в 21:55
поделиться

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

0
ответ дан 30 November 2019 в 21:55
поделиться

Так же, как возможное технологическое изменение Вы могли бы рассмотреть использование MSMQ или чего-то подобного.

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

Конечно, это предполагает, что Вы работаете с платформой Microsoft.

1
ответ дан 30 November 2019 в 21:55
поделиться

Вы пытаетесь реализовать de "База данных как IPC" антишаблон. Ищите его для понимания, почему необходимо рассмотреть перепроектирование программного обеспечения правильно.

-4
ответ дан 30 November 2019 в 21:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: