2016-10-07 2 views
1

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

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

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

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

ответ

1

Вы можете использовать решение, которое реализует консенсусный протокол. Скажем, например, что все ваши узлы в кластере могут связываться с помощью Raft protocol. Таким образом, всякий раз, когда узел X захочет начать работу над задачей Y, он попытается зафиксировать сообщение X starts working on Y. Когда такие сообщения будут переданы в журнал, все узлы будут видеть все сообщения в журнале в том же порядке.

Когда узел X завершает или прервет задачу, он попытается зафиксировать X no longer works on Y, чтобы другой узел мог начать/продолжить работу над ним.

Это может случиться так, что два узел (X и Z) может попытаться совершить их старта сообщений одновременно, и журнал будет выглядеть примерно так:

... 
N-1: ... 
N+0: "X starts working on Y" 
... 
N+k: "Z starts working on Y" 
... 

Но так как нет X no longer works on Y сообщения между записью N + 0 и N + k, каждый узел (включая Z) знал бы, что Z не должен начинать работу над Y.

Единственная оставшаяся проблема заключается в том, что если узел X был разбит на разделы из кластера, попытайтесь зафиксировать его X no longer works on Y, для которого я считаю, что есть n o идеальное решение.

Обходной способ может заключаться в том, что X будет периодически совершать сообщение X still works on Y at time T, и если такое сообщение не было зафиксировано в журнале для некоторой пороговой продолжительности, кластер предположил бы, что никто больше не работает над этой задачей.

С этим обходным способом, однако, вы позволите, чтобы два или более узла работали над одной и той же задачей (секционированный узел X и некоторый новый узел, который поднимает задачу после таймаута).

0

После тщательного поиска я пришел к выводу, что эту проблему можно решить методом fencing.

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

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