Theorie von Peer-to-Peer-Netzwerken: Tapestry Peter Janacik [email protected] Institut für Informatik, Universität Paderborn Seminar Perlen der Theoretischen Informatik‘ ’ AG Algorithmen und Komplexität 11. Januar 2004 Inhaltsverzeichnis 1 Einleitung 1.1 Frühe Ansätze . . . . . . . . . 1.2 Systeme auf Basis dynamischer, 1.3 Zielsetzungen . . . . . . . . . . 1.4 Vergleichskriterien . . . . . . . . . . . . . . . . . . . . . verteilter Hashtabellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2 3 4 4 2 CAN, Chord, Pastry 2.1 CAN . . . . . . . . . . . . . . 2.1.1 Struktur . . . . . . . . 2.1.2 Routing . . . . . . . . 2.1.3 Konstruktion . . . . . 2.1.4 Designverbesserungen 2.2 Chord . . . . . . . . . . . . . 2.2.1 Struktur . . . . . . . . 2.2.2 Konstruktion . . . . . 2.2.3 Routing . . . . . . . . 2.3 Pastry . . . . . . . . . . . . . 2.3.1 Struktur . . . . . . . . 2.3.2 Routing . . . . . . . . 2.3.3 Konstruktion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 4 4 5 5 6 6 6 6 7 7 7 8 9 3 Tapestry 3.1 Struktur . . . . . . . . . . . . . 3.2 Routing . . . . . . . . . . . . . 3.2.1 Publikation . . . . . . . 3.2.2 Anfragen . . . . . . . . 3.2.3 Surrogate Routing . . . 3.3 Konstruktion . . . . . . . . . . 3.3.1 Einfügen eines Knotens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 9 10 10 10 11 12 12 4 Abschlussbetrachtung 14 Abbildung 1: (a) Lookup von Datei 771 mit zentralem Server, (b) mit Flooding, (c) mit dynamischer, verteilter Hashtabelle in einem ortsunabhängigen Netzwerk. Mit einem Stern markierte Knoten besitzen Verweise auf das gesuchte Datenobjekt bzw. das Datenobjekt selbst. Anfragen sind lang gestrichelt gezeichnet, Antworten kurz. 1 Einleitung Peer-to-Peer-Systeme und -Applikationen sind verteilte Systeme, d. h. Systeme ohne eine hierarchische Organisation und ohne eine zentrale Kontrollinstanz, wobei Knoten des Systems Software mit äquivalenter Funktionalität ausführen. Grundsätzlich ist es möglich, Peer-to-Peer-Filesharing-Systeme bei verschiedenen Netzwerktypen einzusetzen, wie z. B. in Ad-hoc-Netzwerken, die auf spezialisierten Netzwerkprotokollen aufbauen, oder in z. B. IP-basierten Netzwerken, wie dem Internet. Diese Ausarbeitung beschränkt sich auf Peer-to-Peer-Systeme des letzteren Typs, in denen bei einer gegebenen Adresse das Routing von der Netzwerkschicht durchgeführt wird. 1.1 Frühe Ansätze Die vielleicht bekanntesten und ältesten Peer-to-Peer-Systeme sind Napster, die Gnutella-Netzwerke, sowie das Kazaa-Netzwerk. Napster, das Mitte 1999 startet, ermöglicht den Austausch von Daten zwischen gleichrangigen Benutzern bzw. Peers, während es gleichzeitig einen zentralen Server zum Auffinden von Dateirepliken benötigt [RF01]. Die Nachteile des zentralen Lookup-Mechanismus von Napster bestehen vor allem in den hohen Kosten des zentralen Servers, erhöhtem Ausfallrisiko (Single Point of Failure) und Verwundbarkeit durch Angriffe von außen. Abbildung 1 (a) zeigt diese Architektur. Gnutella – als Beispiel für ein weiter entwickelteres System – eliminiert diese Nachteile, indem es eine verteilte Suche verwendet. Da Suchanfragen bei diesem System von Knoten zu Knoten weitergeleitet werden und somit das Netzwerk fluten (siehe Abbildung 1 (b)), ist es nicht skalierbar [RF01]. Kazaa baut auf einem ähnlichen Prinzip auf, mit dem Unterschied, dass es zwischen normalen und Super” nodes“ unterscheidet, wobei letztere zusätzlich für die Verwaltung von Suchanfragen 2 zuständig sind [LR03]. Die Entscheidung für einen der beiden Modi hängt von der Bandbreite des Knotens ab [KA]. Leider sind durch das Fluten des Netzwerkes mit Suchanfragen nur zu der Anzahl der Knoten lineare Laufzeiten zu erreichen. Gleichzeitig ist aufgrund der erhöhten Netzwerklast die Reichweite der Anfragen stark eingeschränkt. Die in dieser Ausarbeitung dargestellten Verfahren nehmen sich mit Hilfe von dynamischen, verteilten Hashtabellen genau der beiden zuletzt genannten Nachteile an. 1.2 Systeme auf Basis dynamischer, verteilter Hashtabellen Obwohl im Zusammenhang mit Peer-to-Peer-Systemen häufig Themen wie Sicherheit, Anonymität, etc. diskutiert werden, besteht die Kernoperation dieser Systeme aus der effizienten Auffindung von Datenobjekten. Systeme der aktuellen Generation – wie die in dieser Ausarbeitung vorgestellten – bauen auf dynamischen, verteilten Hashtabellen – und damit einhergehend – auf dem ortsunabhängigen Routing (location-independent routing) auf. Dynamische, verteilte Hashtabellen dienen der gleichmäßigen Verteilung von Datenobjektverweisen auf die Knotenmenge. Ortsunabhängiges Routing ermöglicht das Routing von Anfragen mit Hilfe von Namen, die unabhängig von dem physikalischen Standort des Zieldatenobjektes sind [HK02]. In der Tat gleichen die Operationen auf den meisten hier vorgestellten Systemen den Operationen auf Hashtabellen: Insert, Lookup, Delete. Den in dieser Ausarbeitung behandelten Systemen liegen die folgenden zwei Komponenten zugrunde: ¦ Daten: Die Datenobjekte, die anderen Nutzern des Systems zur Verfügung gestellt werden, sind beliebig auf die Knoten verteilt. Abgesehen vom Caching, werden keine Daten verschoben, um die Effizienz des Auffindens dieser zu verbessern. ¦ Zeiger auf Daten, bzw. Verzeichniseinträge: Jeder Knoten ist dafür zuständig, Zeiger auf eine Teilmenge von Datenobjekten zu verwalten. Eine einfache Hashtabelle als Beispiel: Knoten 1 verwaltet alle Zeiger auf Datenobjekte, mit Namen von a.. bis af.., Knoten 2 ag.. bis bb.., etc. Gleichzeitig schließt das Verfahren aber Redundanzen zur Leistungssteigerung nicht aus. Das Herausfinden des Standorts eines Datenobjekts besteht aus zwei Hauptschritten (siehe auch Abbildung 1 (c)): 1. Auffinden des Knotens, welcher den Zeiger bzw. Verzeichniseintrag auf das gesuchte Datenobjekt enthält. 2. Nachschlagen des Quellknotens des gesuchten Datenobjektes innerhalb des gefundenen Knotens Handelt es sich bei dem Peer-to-Peer-System um ein Filesharing-System, kann nun der anfragende Knoten damit beginnen, das Datenobjekt von dem gefundenen Quellknoten aus mit Hilfe des Routings auf Netzwerkebene zu sich selbst zu kopieren. Mit Hilfe dieses Ansatzes erreichen die hier vorgestellten Systeme zu der Anzahl der Knoten logarithmische Laufzeiten bei der Auffindung von Datenobjekten und sind daher der im letzten Abschnitt vorgestellten Vorgängergeneration mit ihren Nachteilen eines zentralen Servers oder ihren linearen Laufzeiten weit voraus. 3 1.3 Zielsetzungen Zu den Zielsetzungen eines auf dynamischen, verteilten Hashtabellen und ortsunabhängigem Routing basierenden Netzwerks gehören nach [HK02] und [SM01] folgende Punkte: ¦ Deterministische Ortung: Falls Objekte innerhalb des Netzwerks existieren, sollten sie lokalisiert werden können. ¦ Routing-Lokalität: Routen sollten einen geringen Stretchi aufweisen. ¦ Minimalität und Lastbalancierung: Die Infrastruktur sollte keine der Komponenten unnötig belasten, d. h. geringe Anforderungen an Ressourcen stellen und die Belastung innerhalb des Netzwerks gleich verteilen. ¦ Dynamische Mitgliedschaft und Skalierbarkeit: Das System muss sich ankommenden und das Netzwerk verlassenden Knoten anpassen, während es die oben dargestellten Eigenschaften bewahrt. 1.4 Vergleichskriterien Folgende Kriterien dienen dem Vergleich der später vorgestellten Systeme: ¦ Insert Cost: Kosten für das Einfügen von Knoten in das System inklusive der Kosten für die Aufrechterhaltung einer bestimmten Struktur. ¦ Space: Kosten für die Speicherung der Einträge, die zur Verwaltung des Systems benötigt werden. ¦ Hops: Anzahl der Hops, bis ein Objekt geortet ist. ¦ Balance: Gibt es eine Lastverteilung zwischen den Knoten? Der verbleibende Teil dieser Ausarbeitung geht nach einem Überblick über verwandte Systeme schwerpunktmäßig auf Tapestry ein, da dieses System durch seine hervorragende Stretch-Eigenschaft aus der Menge hervorsticht. Dabei befasst sich die Darstellung vor allem mit den Aspekten Struktur, Konstruktion und Routing, da anhand dieser die Architektur, Funktion und die Eigenschaften der Systeme besonders deutlich werden. Zum Schluss folgt ein abschließender Vergleich. 2 CAN, Chord, Pastry Obwohl CAN [RF01], Chord [SM01], Pastry [RD01] und Tapestry [HK02] die in der Einleitung aufgeführten Gemeinsamkeiten besitzen, weisen sie in der Struktur und der Organisation des Netzwerks interessante Unterschiede auf. 2.1 2.1.1 CAN: A Scalable Content-Addressable Network Struktur Der Begriff des Content-Addressable Network bezeichnet die von den Autoren von [RF01] vorgeschlagene Variante des ortsunabhängigen Routing anhand einer dynamischen, verteilten Hashtabelle. Jeder der Knoten im CAN ist jeweils für einen bestimmten Teil – bei CAN Zone genannt – der gesamten Hashtabelle verantwortlich. In Abbildung 2 ist auf i Quotient aus der Entfernung zwischen dem Sender der Anfrage und der Datenquelle und der minimalen Entfernung zwischen dem Sender der Anfrage und der Datenquelle 4 Abbildung 2: Aufbau eines CAN mit d = 2, n = 6, 7 und Wertebereich [0, 1] × [0, 1]. In Zone 4 wird ein neuer Knoten eingefügt. der linken Seite ein CAN, bestehend aus einem d-Thorus mit sieben Knoten und der Dimension d = 2 innerhalb der Koordinaten [0, 1] × [0, 1] dargestellt. Das Koordinatensystem ist rein logisch und steht in keinem Zusammenhang zum physikalischen Koordinatensystem. Ein Schlüssel, also z. B. ein Datenobjektname, wird innerhalb des Koordinatensystems deterministisch mit Hilfe einer gleichverteilten Hashfunktion auf einen Punkt P abgebildet. Anschließend wird der Verweis auf das Datenobjekt in dem Knoten gespeichert, der den Punkt P verwaltet. In dem Beispiel aus Abbildung 2 würde der Punkt P = (0.3, 0.45) in die Zone 6 fallen, da Knoten 6 die Verantwortung für die Hashwerte (0.25 − 0.5, 0.25 − 0.5) übernimmt. 2.1.2 Routing Routing findet innerhalb des CAN über das Weiterleiten von Anfragen an Nachbarzonen bzw. -knoten statt. Zu diesem Zweck unterhält jeder Knoten eine RoutingTabelle mit den IP-Adressen seiner Nachbarn. Beispiel: Eine Anfrage aus Zone 2 in Abbildung 2 für P = (0.77, 0.9) würde über (2, 5, 4), (2, 6, 1, 4) oder (2, 6, 4) zu Knoten 4 weitergeleitet. Selbst bei Ausfällen einzelner Knoten, in diesem Beispiel z. B. Knoten 5 und 6, wäre eine Weiterleitung der Anfrage möglich. In einem d-dimensionalen Koordinatensystem sind zwei Knoten Nachbarn, wenn ihre Koordinatenabschnitte sich entlang d − 1 Dimensionen überlappen und entlang einer Dimension angrenzen. Daher ist bei einem d-dimensionalen Koordinatensystem, das in n gleiche Zonen unterteilt ist, die durchschnittliche Länge des Routingweges (d/4)(n1/d ) und jeder einzelne Knoten verwaltet 2 d Nachbarn. Dieses bedeutet, dass bei einer Dimension d und bei einer wachsenden Anzahl von Knoten die Anzahl der Nachbarn und somit die Größe der davon abhängigen Zustandsdaten je Knoten gleich bleibt, während die Pfadlänge nur im Rahmen von O(n1/d ) wächst. 2.1.3 Konstruktion Das Hinzufügen von Knoten läuft in drei Schritten ab: 1. Auffinden eines Knotens v im Netzwerk. 2. Auffinden des Knotens, dessen Zone gespalten werden soll, mit Hilfe des CANRouting-Mechanismus von Knoten v aus. Für die Bestimmung eines geeigneten Einfügepunktes P gibt es je nach Art des Netzes verschiedene Möglichkeiten: Wenn die zugrundeliegende Topologie keine Rolle spielt, wird z. B. ein zufälliger Punkt gewählt. 3. Aufspalten der Zone und Benachrichtigung der Nachbarn 5 Abbildung 3: Chord-Ring mit 10 Knoten und fünf Schlüsseln 2.1.4 Designverbesserungen Das CAN-Basissystem bietet viel Platz für Modifikationen und Erweiterungen, hier nur zwei der in [RF01] genannten: ¦ Dimensionen: Eine größere Anzahl der Dimensionen verringert die Länge des Routing-Pfades. Gleichzeitig erhöht sie leicht die Größe der Daten, die in jedem Knoten gespeichert werden müssen, da je Knoten mehr angrenzende Knoten bzw. Zonen verwaltet werden. Bei einem System mit n Knoten und d Dimensionen beträgt die Routing-Pfadlänge O(d(n1/d )) im Idealfall. Mehr Dimensionen und damit mehr Nachbarn führen zusätzlich zu einer gesteigerten Ausfalltoleranz des Netzwerkes. ¦ Realitäten: Realitäten sind Koordinatensysteme innerhalb eines CAN mit mehreren Koordinatensystemen. Jeder Knoten ist in jeder der r Realitäten für eine unterschiedliche Zone zuständig und verwaltet somit r verschiedene Nachbarschaftsmengen. Die Informationen der Hashtabelle werden zwischen den Realitäten repliziert. So wird der Punkt (x, y) bei r = 3 von drei unterschiedlichen Knoten verwaltet. Das Auffinden des Punktes (x, y) reduziert sich folglich auf das Auffinden dieses Punktes in mindestens einer der Realitäten. Da die Punkte, an denen sich ein Knoten befindet, in jeder Realität unterschiedlich sind, hat ein Knoten die Fähigkeit weit entfernte Teile des Koordinatenraumes in nur einem Hop zu erreichen. 2.2 Chord: A Scalable Peer-to-Peer Lookup Protocol for Internet Applications In [SM01] stellen die Autoren ein skalierbares Lookup-Protokoll für Internet Applikationen vor. Ebenso wie CAN, stellt Chord die von Hashtabellen bekannten Funktionen zur Verfügung. 2.2.1 Struktur Innerhalb des Chord-Netzwerkes sind Knoten mit Identifikatoren der Länge m auf einem Chord-Ring der Größe 2m angeordnet, wie Abbildung 3 darstellt. 2.2.2 Konstruktion Die Funktion successor(k) liefert den Knoten, dessen Identifikator gleich dem Identifikator k ist oder diesem als Erstes im Uhrzeigersinn auf dem Ring folgt. Das 6 Abbildung 4: (a) Verknüpfung eines Chord-Ringes bei einfachem Routing. Durchgehend gezeichnete Pfeile: Successor-Verweise. Gestrichelte Pfeile: Anfrage von Knoten 14 über Schlüssel 59. (b) Verknüpfung eines Chord-Ringes bei skalierbarem Routing. Durchgehende Pfeile mit Bezeichnung der Schrittgröße: Zusätzliche Finger-Verweise (nur von Knoten 14 und 48 ausgehend dargestellt). Einfügen eines neuen Schlüssels k erfolgt an dem Knoten successor(k). Das Betreten des Netzwerkes durch einen Knoten vi mit Identifikator id(vi ) erfolgt durch die folgenden Schritte: 1. Auffinden des Knotens vs = successor(vi ) 2. Übernahme aller Schlüssel durch vi von vs , die kleiner oder gleich id(vi ) sind. 2.2.3 Routing Die Autoren von [SM01] sehen zwei Arten von Routing vor: ¦ Einfaches Routing: Einfaches Verfolgen der successor-Zeiger bis der für den Schlüssel verantwortliche Knoten gefunden ist. Erfordert je Knoten die Speicherung weniger Zustandsdaten, ist jedoch in der Laufzeit linear zu der Knotenzahl. Abbildung 4 (a) zeigt ein Beispiel mit einem anfragenden Knoten 14 und dem gesuchten Schlüssel 59. ¦ Skalierbares Routing: Bei diesem Routing verwaltet jeder Knoten eine FingerTabelle der Größe mii . Der i-te Eintrag in der Tabelle für Knoten n enthält successor(n + 2i−1 ). Das Routing folgt jeweils dem Verweis in der FingerTabelle, der gleich oder der nächst-kleinere zum gesuchten Wert ist. Das Beispiel in Abbildung 4 (b) zeigt die Finger-Tabellen von Knoten 14 und 48. Die Autoren von [SM01] beweisen, dass mit hoher Wahrscheinlichkeit die Laufzeit dieses Routing O(log N ) mit Knotenzahl N beträgt. 2.3 2.3.1 Pastry: Scalable, decentralized object location and routing for large-scale peer-to-peer systems Struktur Jeder Knoten verwaltet folgende Elemente als Zustand: ¦ Routing-Tabelle R: Jede der dlog2b N e Zeilen besitzt 2b − 1 Einträge. N stellt die Anzahl der Knoten dar, b ist die Anzahl der für die Kodierung eines Zeichens benutzten Bits, mit dem typischen Wert 4. Jeder der Einträge in Zeile n ii m Anzahl der Bits im Schlüssel- bzw. Knotenidentifikator 7 Abbildung 5: Zustand eines Pastry-Knotens mit Identifikator 10233102, b = 2, l = 8 und Basis 4 für alle angeführten Zahlen. Allein in einem Feld angeführte Zahlen beinhalten die Ziffer des Identifikators des aktuellen Knotens an n-ter Stelle. Die restlichen Identifikatoren sind aufgeteilt in: Gemeinsamer Präfix mit 10233102 - nachfolgende Ziffer - Rest. und Spalte j der Routing-Tabelle verweist auf einen Knoten, dessen Identifikator mit dem des aktuellen Knotens in den ersten n Stellen übereinstimmt und an der n+1-ten Stelle das j-te Symbol des Alphabets aufweist. Eine Ausnahme bildet jeweils der Eintrag für das n + 1-te Symbol des eigenen Identifikators. Falls zu einem Eintrag keine passenden Knoten gefunden werden, bleibt dieser leer. ¦ Nachbarschaftsmenge M: Enthält die Identifikatoren der |M | Knoten, die anhand eines bestimmten Proximitätsmaßes am nächsten zum aktuellen Knoten liegen. Diese Menge dient nicht dem Routing, sondern der Aufrechterhaltung von Lokalitätseigenschaften. |M | wird auf 2b oder 2b+1 gesetzt. ¦ Blattmenge L: Enthält |L|/2 Identifikatoren, die nächstkleiner, und |L|/2 Identifikatoren, die nächstgrößer als der Identifikator des aktuellen Knotens sind, mit |L| = |M |. Abbildung 5 enthält den Zustand eines Pastry-Knotens mit b = 2 und l = 8. 2.3.2 Routing Geht eine Anfrage nach Schlüssel k ein, führt der betreffende Knoten mit Identifikator a folgenden Algorithmus aus: ¦ Falls k von dem Bereich der Blattmenge L abgedeckt wird, leite die Anfrage an den Knoten aus L weiter, dessen Identifikator numerisch k am nächsten ist. Dieses ist der Zielknoten. ¦ Sonst leite die Anfrage anhand der Routing-Tabelle an den Knoten weiter, dessen Identifikator mit k in mindestens einer Stelle mehr übereinstimmt als a. ◦ Findet sich kein solcher Knoten in der Routing-Tabelle oder ist dieser nicht erreichbar, dann leite die Nachricht an einen Knoten weiter, dessen Identifikator aus R ∪ M ∪ L einen gemeinsamen Präfix mit k besitzt, der mindestens genauso lang ist wie der gemeinsame Präfix von k und a, und numerisch näher als k und a. 8 Das oben beschriebene Verfahren konvergiert, da die Anfrage immer zu einem Knoten mit einem Identifikator weitergeleitet wird, der mit k einen längeren Präfix gemeinsam hat, oder mit k einen gleichlangen Präfix gemeinsam hat wie a und k numerisch näher ist. Zusätzlich lässt sich zeigen, dass unter der Annahme korrekter Routing-Tabellen und keiner kürzlichen Knotenausfälle, die Anzahl der RoutingSchritte dlog2b N e mit Knotenzahl N ist. 2.3.3 Konstruktion Die Ankunft eines Knotens setzt voraus, dass der neue Knoten mindestens einen bereits im System integrierten Knoten A kenntiii , der dem verwendeten Proximitätsmaß nach in seiner Nähe ist. Die Integration des neuen Knotens in das Netzwerk verläuft folgendermaßen: 1. Neuer Knoten N berechnet den eigenen Identifikator niv . 2. Anfrage von N an A über das Routing nach n ergibt Knoten B, dessen Identifikator b numerisch n am nächsten ist. Während des Routings senden alle daran beteiligten Knoten ihre Zustandsinformationen an N . 3. N inspiziert die erhaltenen Zustandselemente und passt den eigenen Zustand entsprechend an. Dabei übernimmt er als Ausgangszustand M von A, L von B und Zeile n in R von dem n-ten Knoten auf dem Routingweg zwischen A und B. 4. N informiert alle relevanten Knoten von seiner Ankunft. 3 Tapestry: Distributed Object Location in a Dynamic Network 3.1 Struktur Jeder Knoten A mit Identifikator a aus einem Alphabet der Größe b in einem A Tapestry-Netzwerk verwaltet |Nβ,j | = b |a| Nachbarschaftsmengen. Eine NachbarA schaftsmenge Nβ,j des Knotens A beinhaltet Verweise auf Knoten, deren Identifikatoren einen Präfix β mit a gemeinsam haben und an der Stelle l = |β| + 1 das Symbol j aufweisen. Abbildung 6 zeigt die Nachbarschaftsmengen des Knotens 4221 und Nachbarschaftsebenen l = 1, 2, 3, 4. A Für jedes j und β heißt der am nächsten liegende Knoten in Nβ,j primärer A Nachbar, alle anderen heißen sekundäre Nachbarn. Nβ,j = ∅ für ein bestimmtes β, j und A wird Loch genannt. Tapestry bildet den Identifikator ψ eines Datenobjektes mit der Funktion Rψ = maproots(ψ) auf die Menge Rψ der Wurzelknoten ab. Die Funktion maproots(ψ) muss existierende Knoten liefern. |Rψ | ist konstant für alle Elemente und ≥ 1. Das Tapestry-Netzwerk besitzt – wie die Autoren in [HK02] zeigen – folgende Eigenschaften, die sich aus der Struktur des Netzes und aus dem Routing-Verfahren ergeben: A = ∅ für ein beliebiges A, dann existieren keine ¦ Konsistenz (1): Falls Nβ,j Knoten mit (β, j) in dem Netzwerk. iii z. iv z. B. durch einen expanding ring“ IP multicast ” B. durch einen SHA-1-Hash der eigenen IP-Adresse 9 Abbildung 6: Nachbarschaftsmengen des Knotens 4221 in einem TapestryNetzwerk. Nachbarschaftsknoten sind durch Kanten verbunden. Gestrichelt dargestellte Kreise markieren die Ebenen. Übereinstimmende Präfixe sind fett gedruckt. ¦ Lokalität (2): In jedem PRR- [PR97] und Tapestry-Netzwerk beinhaltet jede A Nachbarschaftsmenge Nβ,j die am nächsten liegenden (β, j)-Nachbarn gemäß eines bestimmten Maßes. ¦ Eindeutige Wurzelknotenmenge (3): Die Wurzelmenge Rψ ist für ein Objekt ψ eindeutig, d. h. maproots(ψ) muss von jedem Knoten im Netzwerk aus das gleiche Ergebnis liefern. 3.2 3.2.1 Routing Publikation Knoten, die Objekte anbieten, publizieren diese Tatsache, indem sie eine publishNachricht an alle Wurzelknoten schicken. Empfängt ein Knoten eine publish-Nachricht, so schickt er diese entlang des jeweiligen Verweises (siehe Abschnitt 3.2.3) an einen Nachbarn weiter und speichert einen Verweis auf das publizierte Objekt. Dabei speichert er bei mehrfach vorhandenen Objekten einen Verweis auf jede der ihm bekannten Repliken. Abbildung 7 (a) zeigt die Publikation von zwei Objekten zum Wurzelknoten 4378 hin. Um die Fehlertoleranz zu verbessern, werden Verweise in einem Soft-State gespeichert, d. h. laufen nach einer bestimmten Zeit aus und müssen erneut publiziert werden. 3.2.2 Anfragen Falls ein Knoten eine Anfrage nach Objekt ψ empfängt und er einen Verweis auf dieses Objekt besitzt, leitet er die Anfrage entsprechend des Verweises weiter. Gibt es mehrere Verweise auf das gleiche Objekt, so wird die Replik bevorzugt, die am nächsten liegt. Hat er keinen Verweis auf das Objekt ψ, schickt er die Anfrage entlang eines Nachbarn in Richtung“ eines Wurzelknotens, wie der nächste Abschnitt ” genauer erläutert. Abbildung 7 (b) zeigt ein Beispiel für das Routing von Anfragen von drei verschiedenen Knoten aus. Nur im ungünstigsten Fall ist ein Routing bis zu einer der Wurzeln nötig, da die Publikation eines Objektes auf allen durchlaufenen Knoten einen Objektverweis hinterlässt. Daher folgendes Theorem [HK02]: Theorem PRR und Tapestry führen ortsunabhängiges Routing durch, wenn die Eigenschaft der eindeutigen Wurzelknotenmengen (3) gegeben ist. 10 Abbildung 7: (a) Publikation im Tapestry-Netzwerk. Objekte werden entlang der gestrichelt gezeichneten Pfeile zum Wurzelknoten hin publiziert. Durchgehende Pfeile stellen die dabei entstandenen Objektverweise dar. 437A und 4377 enthalten je Replik einen Verweis. Präfixübereinstimmungen mit dem Wurzelknoten werden mit fetter Schrift dargestellt. (b) Anfrage im Tapestry-Netzwerk. Drei verschiedene Anfragen entlang der gestrichelt gezeichneten Pfeile unter Ausnutzung der Objektzeiger auf dem Weg zur Wurzel. Beweis Der Publikationsprozess stellt sicher, dass jeder der Wurzelknoten aus Rψ Verweise auf jede der Repliken von ψ besitzt. Daher trifft eine Anfrage an einen beliebigen Wurzelknoten A spätestens bei dem Erreichen von A auf den Verweis auf ψ. Daraus ergibt sich die Beobachtung zur Fehlertoleranz Falls |Rψ | > 1 und die Identifikatoren in Rψ sind unabhängig voneinander, so können Anfragen wiederholt und somit Fehler im Netzwerk toleriert werden. 3.2.3 Surrogate Routing Da in einem dynamischen Netzwerk die Verwaltung von Routing-Verweisen problematisch sein kann, legen die Autoren von [HK02] primär Wert auf die Gewährleistung der o. g. Konsistenzeigenschaft. Daher schlagen sie das Surrogate Routingv vor, bei dem Anfragen nicht mehr – wie bei dem normalen Routing – mit dem Identifikator des Wurzelknotens versehen werden, welcher aus den Identifikatoren der Menge aller Wurzelknoten bei Generierung der Anfrage mit Hilfe einer Zufalls-Funktion bestimmt wird. Statt dessen werden Anfragen nach einem Objekt ψ so behandelt, als wenn der Identifikator von ψ der des Wurzelknotens selbst wäre. So bleiben Anfragen von eventuellen Ausfällen oder Veränderungen in der Wurzelknotenmenge unbeeinflusst – ein Ausfall in dem Wurzelknoten, d. h. eine Nicht-Übereinstimmung nach korrekter Auflösung ist sogar einkalkuliert. Ein Beispiel hierfür ist in Abbildung 7 (a) dargestellt: Knoten 437A kann das Objekt mit Identifikator 4378 zunächst nicht weiterleiten, weil er Löcher in den Nachbarschaftsmengen 437{A,B,C,D,E,F,0,1,2,3,4,5,6} aufweist. Dennoch wählt er unter Anwendung des Tapestry-nativen Routings (siehe unten) den Verweis auf den Knoten mit Identifikator 4377 – danach scheitert“ die Anfrage ” im Wurzelknoten. Das Routing anhand lokaler, das Ziel betreffender Entscheidungen nennen die Autoren auch lokalisiertes Routing. Die beiden in [HK02] vorgestellten Varianten funktionieren wie folgt: v dt. Stellvertreter- oder Ersatz-Routing 11 ¦ Tapestry-natives Routing: Sequentielle Auflösung der Ziffern. Bei Antreffen eines Loches wählt der Algorithmus das nächst-höhere j im Alphabet. Falls z. B. j = 4 bei einem gegebenen β nicht vorhanden ist, fällt die Wahl auf das nächst-vorhandene, größere Symbol im Alphabet. Bei dem Erreichen des größten Zeichens des Alphabets, fährt die Suche beim kleinsten Zeichen fort. ¦ Verteiltes, PRR-ähnliches Routing: Sequentielle Auflösung der Ziffern mit folgenden Regeln: ◦ Vor dem Antreffen des ersten Lochs: Wie beim Tapestry-nativen Routing ◦ Beim Antreffen des ersten Lochs: Wähle den Nachbarn aus, dessen Symbol in möglichst vielen signifikanten Bits dem fehlenden Symbol gleicht. Gibt es mehrere davon, wähle den Verweis mit der numerisch höheren Ziffer. ◦ Nach dem ersten Loch: Wähle die numerisch höchste Ziffer. Der Algorithmus routet zu der Wurzel mit dem numerisch höchsten Identifikator, der in den signifikantesten Bits mit dem Zielidentifikator übereinstimmt. Beide Algorithmen halten an, wenn der aktuelle Knoten, der letzte übrig gebliebene Knoten auf oder oberhalb der aktuellen Ebene der Routing-Tabelle ist. Dieses ist dann der Wurzelknoten. 3.3 3.3.1 Konstruktion Einfügen eines Knotens Das Einfügen eines Knotens in das Netzwerk ist besonders interessant, weil es sehr gut deutlich macht, wie Tapestry seinen besonders niedrigen Stretch erreicht, indem es die unterliegende Topologie des Netzwerks in die Konstruktion mit einbezieht. Um bei dem Einfügen eines Knotens ein gültiges Tapestry-Netzwerk zu erhalten, müssen wir eine zusätzliche Eigenschaft zu den drei bereits oben genannten hinzunehmen, da das Ergebnis der Einfügeoperation das Gleiche sein soll, als wenn das Netz von Grund auf gebaut worden wäre: ¦ Eigenschaft (4): Falls Knoten A auf dem Pfad zwischen dem publizierenden Knoten von Objekt O und dessen Wurzel liegt, dann besitzt A einen Verweis auf O. Das Einfügen eines Knotens in einem Tapestry-Netzwerk verläuft in den folgenden Schritten: 1. Kopieren der Nachbarschaftstabelle von einem mit Hilfe von Routing nach dem eigenen Identifikator gefundenen Surrogatevi -Knoten. 2. Erstellung einer Liste aller Knoten, die α als Präfix haben. α wird zuvor auf den größten gemeinsamen Präfix ggP des neuen Knotens und seinem Surrogate gesetzt. Zum Erstellen der Liste schlagen die Autoren von [HK02] den Acknowledged Multicast-Algorithmus vor: (a) Der neue Knoten sendet eine Acknowledged Multicast Message (im Folgenden kurz Nachricht“), bestehend aus einem Präfix α und einer Funk” tion (siehe unten) an seinen Surrogate. Eine Nachricht ist nur dann gültig, wenn α ein Präfix des Identifikators des empfangenden Knotens ist. vi Knoten mit Identifikator, der numerisch am nächsten zum eigenen Identifikator ist. 12 (b) Empfängt ein Knoten A die Nachricht, sendet er sie an einen Knoten aus A jeder Nachbarschaftsmenge Nα,j weiter. Ein Empfänger kann die Nachricht auf verschiedenen Ebenen, d. h. mit unterschiedlichen αs empfangen. (c) Empfängt ein Knoten eine Nachricht, die nicht mehr weitergeleitet werden kann, wendet er die in der Nachricht gespeicherte Funktion linkAndXferRoot an, welche Verweise, die auf dem neuen Knoten gespeichert werden sollten, zu diesem kopiert und nicht mehr benötigte Verweise löscht. Somit verhindert der Algorithmus, dass Objekte unerreichbar werden. (d) Jeder Knoten, der eine Nachricht verschickt hat, wartet auf Bestätigungen von allen seinen Kindern, d. h. allen Empfängern dieser Nachricht. Sind alle Bestätigungen eingetroffen, schickt er eine Bestätigung an seinen Vater, die eine Liste aller Ahnen enthält. Durch die Konsistenzeigenschaft gegeben, gilt in einem Tapestry-Netzwerk, dass wenn ein Knoten mit Identifikator (α, j) existiert, jeder Knoten A mit Identifikator mit Präfix α mindestens einen solchen Knoten kennt. A sendet in dem Falle eine Nachricht weiter. Fasst man alle von einem Knoten zu sich selbst gesendeten Nachrichten zusammen, so ist das Ergebnis ein Spannbaum. Da jeder Knoten nur eine Nachricht empfängt, werden O(k) Nachrichten versandt. Jeder Weg von der Wurzel bis zu einem Blatt ist nicht länger als d, der Durchmesser des Netzwerks. Daher beträgt die Laufzeit des Acknowledged Multicast-Algorithmus O(d k). 3. Aufbauen der Nachbarschaftsmengen: Wir haben nun im vorhergehenden Schritt alle Knoten mit Identifikatoren mit Präfix α mit |α| = i erhalten. Für alle Längen i..0 und für alle Knoten, die einen i-langen gemeinsamen Präfix mit α besitzen, führt der neue Knoten Folgendes durch: (a) Fordere von allen Knoten der i-ten Ebene eine Liste mit Verweisen zu allen Knoten an, die sie aus der i − 1-ten Ebene in ihren Nachbarschaftsmengen gespeichert haben. (b) Sortiere alle Knoten der Ebene i gemäß ihrer Entfernung zu dem neuen Knoten durch Kontaktieren und unter Einsatz einer bestimmten Entfernungsmetrikvii . Dabei prüft jeder kontaktierte Knoten, ob er den neuen Knoten zu der entsprechenden eigenen Nachbarschaftsmenge hinzufügt. Dieser Schritt stellt eine Basis für die Lokalitätseigenschaft (2) und somit für den niedrigen Stretch in Tapestry dar, weil er es dem Routing ermöglicht, über den primären Nachbarn den am nächsten liegenden Knoten in einer Nachbarschaftsmenge zu ermitteln. (c) Beschneide die Listen auf der Ebene i bis auf die am nächsten liegenden k Knoten. Die Autoren zeigen in [HK02], dass falls b > c2 , b Basis des Alphabets und c eine Konstante ist, es ein k = O(log n) gibt, bei dem die Liste jeder Ebene mit hoher Wahrscheinlichkeit genau die k am nächsten liegenden Knoten beinhaltet. (d) Fülle die Nachbarschaftsmengen mit den oben erstellten Listen. Die Laufzeit für das Einfügen ist mit hoher Wahrscheinlichkeit O(log2 n)[HK02]. vii z. B. Anzahl Hops, Ping-Zeit, etc. 13 4 Abschlussbetrachtung Ein Vergleich der in dieser Ausarbeitung angeführten und verwandter Systeme liefert folgendes Bild [HK02], mit Grad d und Knotenzahl n: System CAN CAN, d = log n Chord Pastry Tapestry Naor/Wieder Naor/Wieder, d = log n Insert Cost O(d n1/d ) O(log n) O(log2 n) O(log2 n) O(log2 n) O(d + logd n) O(log n) Space per Node O(d) O(log n) O(log n) O(log n) O(log n) O(d) O(log n) Hops O(d n1/d ) O(log n) O(log n) O(log n) O(log n) O(logd n) O( logloglogn n ) Balance ja ja ja ja ja ja ja Alle hier im Detail vorgestellten Algorithmen ermöglichen die Lokalisierung eines Objekts in logarithmischer Zeit zur Anzahl der Knoten innerhalb eines Netzwerks. Die Basis des Logarithmus kann dabei variieren und weicht in der Regel vom Optimum ab, welches bei O(logd n) liegt. Ein aktueller Ansatz von Naor und Wieder [NW03] garantiert dagegen die gewünschte Eigenschaft, dürfte aber im realen Einsatz schlechter abschneiden als z. B. Tapestry, da er nicht das unterliegende Netzwerk mit in die Betrachtung einbezieht. Doch auch die anderen vorgestellten Systeme bieten durchaus Vorteile: Im Gegensatz zu Tapestry ist Chord weniger komplex und hat unkomplizierte Behandlungsroutinen für das Hinzufügen und Entfernen von Knoten. CAN-Knoten speichern im Gegensatz zu Chord-, Pastry- und Tapestry-Knoten einen Zustand, dessen Größe nicht abhängig von der Anzahl der Knoten im Netzwerk ist. Tapestry hat gegenüber CAN, Chord und Pastry wiederum den enormen Vorteil eines besonders niedrigen Stretch [HK02], da Tapestry die unterliegende Topologie bei der Konstruktion des Netzwerks in Betracht zieht. Das hier vorgestellte Tapestry ist eine Variante von Plaxtons Algorithmus [PR97]. Tapestry hat gegenüber Plaxtons Algorithmus aber voraus, dass es eine Kenntnis der gesamten Knotenmenge nicht voraussetzt. Alles in allem dürfte auch daher Tapestry bei Einsatz unter realen Bedingungen die besten Ergebnisse liefern. Literatur [HK02] Hildrum, K., Kubiatowicz, J. D., Rao, S., Zhao, B. Y., Distributed Object Location in a Dynamic Network, 2002 [KA] Sharman Networks, Kazaa Media Desktop, http://www.kazaa.com/us/index.htm, 2003 [LR03] Leibowitz, N., Ripeanu, M., Wierzbicki, A., Deconstructing the Kazaa Network, 2003 [NW03] Naor, M., Wieder, U., Novel Architectures for P2P Applications: the ContinuousDiscrete Approach, 2003 [PR97] Plaxton, C. G., Rajaraman, R., Richa, A. W., Accessing nearby copies of replicated objects in a distributed environment, in Proc. of the 9th Annual Symp. on Parallel Algorithms and Architectures, Seiten 311-320, Juni 1997 [RD01] Rowstron, A., Druschel, P., Pastry: Scalable, decentralized object location and routing for large-scale peer-to-peer systems, 2001 [RF01] Ratnasamy, S., Francis, P., Handley, M., Karp, R., Shenker, S., A Scalable ContentAddressable Network, 2001 [SM01] Stoica, I., Morris, R., Liben-Nowell, D., Karger, D. R., Kaashoek, M. F., Dabek, F., Balakrishnan, H., Chord: A Scalable Peer-to-peer Lookup Protocol for Internet Applications, 2001 14