2016-05-27 15 views
3

Ich habe eine verteilte Anwendung, die ZooKeeper für die Führerwahl verwendet. Nur der gewählte Anführer kann sich an die Datenbank binden. Ich habe kürzlich entdeckt, dass es eine potentielle Situation gibt, die zu mehreren Anführern führen könnte. Die Situation entsteht, wenn der gewählte Anführer für einen langen GC angehalten wird und den Herzschlag an den ZooKeeper verlieren kann, was zur Wahl eines neuen Anführers führt. An diesem Punkt denken beide Knoten, dass sie der Anführer sind und zu Konflikten führen können.Zookeeper mehrere Führer Wahl Problem

Irgendwelche Vorschläge, wie man solche Situation vermeiden kann?

+0

Ich würde zuerst untersuchen, warum der GC für so lange pausiert, kann es zu Leistungsproblemen führen. Wenn GC die einzige Ursache ist, muss eine Einstellung länger warten. –

+0

Danke Minh. GC-Pausen sind in den meisten großtechnischen Anwendungen unvermeidlich. Sie können optimieren, um weniger Pausen zu haben, aber das Vermeiden einer langen GC-Pause ist praktisch nicht möglich. Auch das Problem mit der Einstellung, länger zu warten, ist, dass dies zu einer Situation führen könnte, in der es lange keinen Anführer gibt. – Piyg

+1

Sicher, aber so lange zu pausieren, dass das System zu denken droht, es sei nicht ideal. Entweder Sie passen die Wartezeit an oder verringern die Pausenzeit. –

Antwort

1

Wenn Sie ZooKeeper für Leader-Election Sie verwenden nicht Einzigartigkeit des Führers .Es ist möglich laufen in dieser Situation auch ohne GC Pausen garantieren kann. Wenn z. B. ein Leiter während einer Netzwerkpartitionierung vom ZooKeeper-Quorum isoliert ist oder wenn ein Leiter eine lange laufende Abfrage absetzt, können die Dies und ein neuer Leiter eine neue Abfrage ausgeben, während der aktuelle noch aktiv ist.

Die Problemumgehung besteht darin, beim Aktualisieren der Datenbank Compare-and-Set zu verwenden. Sobald ein neuer Anführer gewählt ist, sollten Sie eine ansteigende Anführer-ID erhalten (z. B. indem Sie einen Knoten in ZooKeeper aktualisieren und dessen Version oder mzxid verwenden) und ihn verwenden, um jede von diesem Anführer ausgegebene Transaktion zu schützen.

Wenn Sie zum Beispiel den Zustand des db dann anstelle der folgenden Transaktion ändern möchten:

BEGIN TRANSACTION; 
db.update($change); 
END TRANSACTION; 

Sie sollten

BEGIN TRANSACTION; 
if (db.leaderID <= $leaderID) { 
    db.leaderID = $leaderID; 
    db.update($change); 
} 
END TRANSACTION; 

Dieser Trick wie verwenden, um etwas aus Unsicherheiten Ihr System schützen verursacht durch gleichzeitige Führer. Natürlich sollte Ihre Datenbank linearisierbar sein und Compare-and-Set unterstützen.

+0

Ah, ich verstehe. Sie bestehen also sofort nach der Wahl in der DB und vergleichen und setzen dann zum Zeitpunkt des Commits. Exzellente Idee !! – Piyg