2016-10-07 14 views
1

Ich muss ein verteiltes System entwerfen, bei dem ein Scheduler Aufgaben an Worker in mehreren Knoten sendet. Jeder Aufgabe wird eine ID zugewiesen, und sie kann mehr als einmal ausgeführt werden, geplant vom Scheduler (normalerweise einmal pro Stunde).Verteilte Worker, die sicherstellen, dass eine einzelne Instanz einer Task ausgeführt wird

Meine einzige Anforderung ist, dass eine Aufgabe mit einer bestimmten ID nicht zweimal vom Cluster gleichzeitig ausgeführt werden soll. Ich kann mir ein Design vorstellen, bei dem der Scheduler eine Sperre für jede Aufgaben-ID hält und die Aufgabe an einen geeigneten Mitarbeiter sendet. Sobald der Worker fertig ist, sollte die Sperre aufgehoben werden und der Scheduler könnte sie erneut einplanen.

Was sollte mein Entwurf einschließen, um dies sicherzustellen. Ich mache mir Gedanken über Fälle, in denen eine Aufgabe an einen Arbeiter gesendet wird, der die Aufgabe startet, aber dann den Scheduler nicht darüber informiert.

Was wäre die beste Vorgehensweise in diesem Szenario, um sicherzustellen, dass immer nur eine einzige Instanz eines Jobs gleichzeitig ausgeführt wird?

Antwort

1

Sie könnten eine Lösung verwenden, die ein Konsensprotokoll implementiert. Sagen Sie zum Beispiel, dass alle Ihre Knoten im Cluster unter Verwendung der Raft protocol kommunizieren können. Wenn also ein Knoten X mit der Arbeit an einer Aufgabe Y beginnen möchte, würde er versuchen, eine Nachricht X starts working on Y zu übermitteln. Sobald solche Nachrichten an das Protokoll übergeben wurden, sehen alle Knoten alle Nachrichten im Protokoll in der gleichen Reihenfolge.

Wenn Knoten X die Aufgabe beendet oder abbricht, würde er versuchen, X no longer works on Y zu begehen, damit ein anderer Knoten damit beginnen/weiterarbeiten kann.

Es könnte passieren, dass zwei Knoten (X und Z) versuchen, ihren Start Nachrichten gleichzeitig zu begehen, und das Protokoll würde dann wie folgt aussehen:

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

Aber da es keine X no longer works on Y Nachricht zwischen dem Eintrag N + 0 und N + k würde jeder Knoten (einschließlich Z) wissen, dass Z die Arbeit an Y nicht starten darf.

Das einzige verbleibende Problem wäre, wenn Knoten X vom Cluster partitioniert wurde, bevor er es kann versuchen, seine X no longer works on Y commit für die ich glaube, es gibt n o perfekte Lösung.

Eine Umgehung könnte sein, dass X versuchen würde, eine Nachricht X still works on Y at time T periodisch zu committen, und wenn keine solche Nachricht für eine bestimmte Zeit an das Protokoll übergeben wurde, würde der Cluster davon ausgehen, dass niemand mehr an dieser Aufgabe arbeitet.

Mit dieser Problemumgehung jedoch würden Sie die Möglichkeit zulassen, dass zwei oder mehr Knoten an derselben Aufgabe arbeiten (der partitionierte Knoten X und ein neuer Knoten, der die Aufgabe nach dem Timeout übernimmt).

0

Nach einer gründlichen Suche kam ich zu dem Schluss, dass dieses Problem durch eine Methode namens fencing gelöst werden kann. Wenn Sie vermuten, dass ein Knoten (Worker) fehlgeschlagen ist, besteht die einzige Möglichkeit, sicherzustellen, dass der Rest des Systems nicht beschädigt wird, darin, einen Fence bereitzustellen, der den Zugriff des Knotens auf die von Ihnen benötigte freigegebene Ressource verhindert beschützen. Dies muss eine radikale Methode sein, wie das Zurücksetzen des Computers, der den fehlgeschlagenen Prozess ausführt, oder das Einrichten einer Firewallregel, die verhindert, dass der Prozess auf die freigegebene Ressource zugreift. Sobald der Zaun an seinem Platz ist, können Sie das Schloss, das von dem fehlgeschlagenen Prozess gehalten wurde, sicher aufbrechen und einen neuen Prozess starten.

Verwandte Themen