Die Hauptforschung in diesem Artikel ist der konsequente Algorithmuscode.
Der konsequente Hashing -Algorithmus wurde 1997 vom MIT vorgeschlagen (siehe 0). Das Designziel bestand darin, das Hotpot -Problem im Internet zu lösen, und seine ursprüngliche Absicht war dem Karpfen sehr ähnlich. Konsequentes Hashing korrigiert das Problem, das durch den von Karpfen verwendeten einfachen Hashing -Algorithmus verursacht wird, sodass DHT in P2P -Umgebungen wirklich angewendet werden kann.
Konsequentes Hashing schlägt vier Anpassungsbedingungen vor, die sich der Hashing -Algorithmus in einer dynamisch verändernden Cache -Umgebung treffen sollte:
Gleichgewicht bedeutet, dass das Ergebnis des Hash so weit wie möglich an alle Caches verteilt werden kann, so dass der gesamte Cache -Speicherplatz genutzt werden kann. Viele Hash -Algorithmen können diesen Zustand erfüllen.
Die Monotonität bezieht sich darauf, wenn einige Inhalte durch Hashing in den entsprechenden Cache versandt wurden und dem System neue Caches hinzugefügt werden. Das Ergebnis des Hash sollte sicherstellen, dass der ursprünglich zugewiesene Inhalt dem neuen Cache zugeordnet werden kann, ohne anderen Puffer in der alten Cache -Sammlung zugeordnet zu werden.
Einfache Hashing -Algorithmen können die Anforderungen der Monotonie oft nicht erfüllen, wie den einfachsten linearen Hash:
x → ax + b mod (p)
In der obigen Formel repräsentiert P die Größe aller Caches. Es ist nicht schwer zu erkennen, dass sich alle ursprünglichen Hash -Ergebnisse ändert, wenn sich die Cache -Größe ändert (von P1 nach P2), sich alle ursprünglichen Hash -Ergebnisse ändern, wodurch die Anforderungen der Monotonizität nicht erfüllt werden.
Änderungen in den Hash -Ergebnissen bedeuten, dass beim Änderungsbereich des Cache -Raums alle Zuordnungsbeziehungen im System aktualisiert werden müssen. In P2P -Systemen entsprechen Cache -Änderungen dem Verknüpfen oder Verlassen des Systems. Diese Situation tritt häufig in P2P -Systemen auf, wodurch eine riesige Computer- und Übertragungsbelastung führt. Monotonität erfordert, dass der Hash -Algorithmus diese Situation vermeiden kann.
In einer verteilten Umgebung sieht das Terminal möglicherweise nicht alle Caches, kann aber nur einige von ihnen sehen. Wenn ein Terminal den Inhalt durch den Hashing -Prozess dem Cache abbilden möchte, da der Cache -Bereich, der von verschiedenen Terminals beobachtet wird, unterschiedlich sein kann, ist das Ergebnis des Hashings inkonsistent. Das Endergebnis ist, dass der gleiche Inhalt von verschiedenen Terminals in verschiedene Cache -Bereiche zugeordnet wird. Diese Situation sollte offensichtlich vermieden werden, da sie dazu führt, dass der gleiche Inhalt in verschiedenen Puffern gespeichert wird, wodurch die Effizienz des Systemspeichers verringert wird. Die Definition von Dispersion ist die Schwere der obigen Situation. Ein guter Hashing -Algorithmus sollte in der Lage sein, Inkonsistenzen so weit wie möglich zu vermeiden, dh, um die Dispersion zu minimieren.
Das Lastproblem besteht tatsächlich darin, das Problem der Dezentralisierung aus einer anderen Perspektive zu untersuchen. Da verschiedene Terminals für einen bestimmten Puffer den gleichen Inhalt auf verschiedene Puffer zuordnen können, kann er auch von verschiedenen Benutzern unterschiedlichen Inhaltens zugeordnet werden. Wie Dispersion sollte diese Situation vermieden werden, sodass ein guter Hashing -Algorithmus in der Lage sein sollte, die Pufferlast zu minimieren.
Auf der Oberfläche richtet sich ein konsistentes Hashing auf das Problem der verteilten Pufferung ab. Wenn Sie jedoch Pufferung als Peer in einem P2P -System und den zugeordneten Inhalt als verschiedene gemeinsame Ressourcen (Daten, Dateien, Medienströme usw.) betrachten, werden Sie feststellen, dass die beiden tatsächlich das gleiche Problem beschreiben.
Im konsistenten Hashing -Algorithmus hat jeder Knoten (entsprechend Peer im P2P -System) eine zufällig zugewiesene ID. Wenn Sie Inhalte auf einen Knoten abbilden, wird eine konsistente Hash -Operation unter Verwendung des Schlüsselworts des Inhalts und der ID des Knotens durchgeführt und den Schlüsselwert erhalten. Durch konsequentes Hashing ist der Schlüsselwert und die Knoten -ID im gleichen Wertebereich. Der einfachste Schlüsselwert und die einfachste ID können eindimensional sein, z. B. eine Reihe von Ganzzahlen von 0000 bis 9999.
Beim Speichern von Inhalten basierend auf dem Schlüsselwert wird der Inhalt auf dem Knoten gespeichert, wobei die ID seinem Schlüsselwert am nächsten liegt. Wenn der Schlüsselwert beispielsweise 1001 beträgt, befinden sich Knoten mit IDS 1000, 1010, 1100 im System, und der Inhalt wird auf 1000 Knoten abgebildet.
Um die für die Abfrage erforderlichen Routen zu erstellen, muss der Konsistenz -Hash jeden Knoten die Standortinformationen (IP -Adresse) seines Uplink -Knotens speichern (der ID -Wert ist größer als der kleinste unter seinen eigenen Knoten) und Downlink -Knoten (der ID -Wert ist unter den eigenen Knoten weniger als der größte). Wenn ein Knoten Inhalte finden muss, kann er beschließen, eine Abfrageanforderung an den Uplink- oder Downlink -Knoten basierend auf dem Schlüsselwert des Inhalts zu initiieren. Wenn ein Knoten, der die Abfrageanforderung empfängt, feststellt, dass er das angeforderte Ziel hat, kann er die Bestätigung direkt an den Knoten zurückgeben, der die Abfrageanforderung initiiert. Wenn es feststellt, dass es nicht zu seinem eigenen Umfang gehört, kann es die Anfrage an den Uplink/Downlink -Knoten weiterleiten.
Um die oben genannten Routing-Informationen aufrechtzuerhalten, müssen benachbarte Knoten die Routing-Informationen rechtzeitig aktualisieren. Dies erfordert, dass Knoten nicht nur direkt angeschlossene Downlink-Knoten-Standortinformationen speichern, sondern auch die indirekten Downlink-Knoteninformationen in einer bestimmten Tiefe (N-HOP) kennen und die Knotenliste dynamisch beibehalten. Wenn ein Knoten das System verlässt, versucht der Uplink -Knoten, sich direkt zum nächsten Downlink -Knoten zu verbinden. Nachdem die Verbindung erfolgreich ist, wird die Downlink -Knotenliste aus dem neuen Downlink -Knoten erhalten und seine eigene Knotenliste aktualisiert. Wenn ein neuer Knoten zum System hinzugefügt wird, finden Sie zuerst den Downlink -Knoten gemäß einer eigenen ID und erhalten Sie die Downlink -Knotenliste und bitten Sie dann den Uplink -Knoten, die Liste der Downlink -Knoten zu ändern, wodurch die Routing -Beziehung wiederhergestellt wird.
diskutieren
Konsistentes Hash löst im Grunde genommen das kritischste Problem in einer P2P -Umgebung - wie Speicher und Routing in einer dynamischen Netzwerk -Topologie verteilen. Jeder Knoten muss nur Informationen über eine kleine Anzahl benachbarter Knoten aufrechterhalten, und wenn der Knoten das System verbindet/verlässt, beteiligt sich nur eine kleine Anzahl relevanter Knoten an der Aufrechterhaltung der Topologie. All dies macht konsequentes Hash zum ersten praktischen DHT -Algorithmus.
Der Routing -Algorithmus des konsequenten Hashings hat jedoch immer noch Mängel. Während des Abfrageprozesses muss die Abfragenachricht O (n) Schritt (o (n) eine proportionale Beziehung zu n angeben, und N repräsentiert die Gesamtzahl der Knoten im System), bevor sie den Abfragedous erreichen kann. Es ist nicht schwer vorstellbar, dass die Anzahl der Knoten eine Million überschreiten kann, wenn das System sehr groß ist und eine solche Abfrageeffizienz offensichtlich schwierig ist, die Bedürfnisse der Nutzung zu erfüllen. Aus einer anderen Perspektive, selbst wenn der Benutzer lange Verzögerungen tolerieren kann, bringt die große Menge an Nachrichten, die während des Abfrageprozesses generiert werden, unnötige Last in das Netzwerk.
Paket Herotrix; Import Java.util.Collection; Import Java.util.SorteedMap; Import Java.util.Treemap; öffentliche Klasse konsistenthash <t> {// Hash -Algorithmus private endgültige Hashfunktion Hashfunction; // Anzahl der virtuellen Noten private endgültige number -number -number -number -number -number -number -number -number -number -number -number -number -number -number -number -number -number -number -number -kreis -kreis -number -numer -ofreplicas; Treemap <Integer, t> (); public Consisthash (Hashfunction Hashfunction, int nummerofReplicas, Sammlung <T> Knoten) {this.hashfunction = Hashfunction; this.numberofreplicas = numberofreplicas; für (t Knoten: Knoten) {add (node);}} public void add (t node) {für (int i = 0; i <numberofreplicas; i ++) {Circle.put (Hashfunction.hash (node.toString ()+i), node); i ++) {circle.remove (Hashfunction.hash (node.toString ()+i));}} // Schlüsselalgorithmus public t (Objektschlüssel) {if (Circle.Empty ()) {return null;} // Berechnen Sie Hash -Wert, das nicht int in INT hashfunction (Hashfunction.Hash (Hashfunction if (! circle.containsKey (Hash)) {sortEdMap <Integer, t> TailMap = Circle.TailMap (Hash); Hash = TailMap.isempty ()? Circle.FirstKey (): TailMap.FirstKey ();} return Circle.get (Hash);}}Das obige ist der gesamte Inhalt dieses Artikels über die Java -Sprache konsistente Hash -Algorithmus -Lernnotizen (Codebeispiele). Ich hoffe, es wird für alle hilfreich sein. Interessierte Freunde können weiterhin auf andere verwandte Themen auf dieser Website verweisen. Wenn es Mängel gibt, hinterlassen Sie bitte eine Nachricht, um darauf hinzuweisen. Vielen Dank an Freunde für Ihre Unterstützung für diese Seite!