Verteilte Algorithmen und Datenstrukturen

Werbung
Verteilte Algorithmen und
Datenstrukturen
Kapitel 6: Informationsorientierte
Datenstrukturen
Prof. Dr. Christian Scheideler
SS 2012
12.07.2012
VADS - Kapitel 6
1
Informationsorientierte
Datenstrukturen
• dynamische Menge an Ressourcen (Prozesse)
• dynamische Menge an Informationen (uniforme Datenobjekte)
Beispiel:
Operationen auf Prozessen:
• Join(v): neuer Prozess v kommt hinzu
• Leave(v): Prozess v verlässt das System
Operationen auf Daten: abhängig von Datenstruktur
12.07.2012
VADS - Kapitel 6
2
Informationsorientierte
Datenstrukturen
Grundlegende Ziele:
• Monotone Stabilisierung der Prozessstruktur (so dass
monotone DS-Erreichbarkeit aus beliebigem schwachen
Zusammenhang gewährleistet ist)
• Lokale Konsistenz für Datenzugriffe
Definition 6.1: Die Abarbeitung einer Folge von Operationen
Op1,Op2,…,Opn auf den Daten heißt lokal konsistent, falls
Op1,Op2,…,Opn in der vorgegebenen Reihenfolge vom
System ausgeführt werden.
Wir wollen sicherstellen, dass für jeden Knoten v des Systems
die Operationsfolge von v auf den Daten lokal konsistent
ausgeführt wird. Das erlaubt es allerdings, dass die
Operationsfolgen der Knoten beliebig ineinander verzahnt
werden dürfen.
12.07.2012
VADS - Kapitel 6
3
Informationsorientierte
Datenstrukturen
Beispiel:
v
Insert(x,A), Search(x), Search(y)
Datenstruktur
w
Insert(y,B), Insert(x,C), Delete(x)
Eine lokal konsistente Ausgabe für v wäre C, B, da diese durch
Insert(x,A), Insert(y,B), Insert(x,C) Search(x), Search(y)
zustande käme.
SS 2011
VADS - Kapitel 5
4
Informationsorientierte
Datenstrukturen
Strategien für lokale Konsistenz:
• Routingorientiert: stelle sicher, dass sich
Anfragen derselben Quelle während des
Routings nicht überholen können.
• Quellorientiert: Quelle startet erst dann
neue Anfrage, wenn all ihre vorigen
Anfragen ausgeführt worden sind.
12.07.2012
VADS - Kapitel 6
5
Informationsorientierte
Datenstrukturen
Quellorientierte lokale Konsistenz:
• Stelle für jede Datenanfrage zunächst (über Lookup)
fest, mit welchen Prozessen Daten ausgetauscht
werden. Das kann oft parallel geschehen.
• Führe dann den Datenaustausch sequentiell in der
vorgegebenen Reihenfolge aus.
Anfragen
: Suche
4
3
2
1
: Ausführung
Zeit
12.07.2012
VADS - Kapitel 6
6
Übersicht
•
•
•
•
•
Verteilte Hashtabelle
Verteilte Suchstruktur
Verteilter Stack
Verteilte Queue
Verteilter Heap
12.07.2012
VADS - Kapitel 6
7
Wörterbuch
8
4
11
20
18
3
12.07.2012
VADS - Kapitel 6
8
Wörterbuch
insert(15)
8
4
11
20
15
12.07.2012
18
3
VADS - Kapitel 6
9
Wörterbuch
delete(20)
8
4
11
20
15
12.07.2012
18
3
VADS - Kapitel 6
10
Wörterbuch
lookup(8) ergibt 8
8
4
15
12.07.2012
11
18
3
VADS - Kapitel 6
11
Wörterbuch
lookup(7) ergibt ?
8
4
15
12.07.2012
11
18
3
VADS - Kapitel 6
12
Wörterbuch-Datenstruktur
S: Menge von Elementen
Jedes Element e identifiziert über key(e).
Operationen:
• S.insert(e: Element): S:=S∪{e}
• S.delete(k: Key): S:=S\{e}, wobei e das
Element ist mit key(e)=k
• S.lookup(k: Key): Falls es ein e∈S gibt mit
key(e)=k, dann gib e aus, sonst gib ⊥ aus
Effiziente Lösung: Hashing
12.07.2012
VADS - Kapitel 6
13
Klassisches Hashing
1
3
5
10
14
19
zeit- und speichereffiziente
Hashfunktion h:U→T
14
5
3
19
1
10
Hashtabelle T
12.07.2012
VADS - Kapitel 6
14
Klassisches Hashing
1
3
5
10
14
19
Aufgabe der Hashfunktion:
Gute Streuung der Elemente in T
14
5
3
19
1
10
Hashtabelle T
12.07.2012
VADS - Kapitel 6
15
Klassisches Hashing
1
3
5
10
14
19
Gute Streuung der Elemente in T:
insert, delete, lookup nur O(1) Zeit
14
5
3
19
1
10
Hashtabelle T
12.07.2012
VADS - Kapitel 6
16
Verteiltes Hashing
Hashing auch für verteilte Speicher anwendbar:
1
3
5
10
14
19
Hashfunktion h
Problem: Menge der Speichermedien verändert
sich (Erweiterungen, Ausfälle,…)
12.07.2012
VADS - Kapitel 6
17
Verteiltes Wörterbuch
Grundlegende Operationen:
• insert(d): fügt Datum d mit Schlüssel key(d)
ein (wodurch eventuell der alte zu key(d)
gespeicherte Inhalt überschrieben wird)
• delete(k): löscht Datum d mit key(d)=k
• lookup(k): gibt Datum d zurück mit key(d)=k
• join(v): Knoten (Speicher) v kommt hinzu
• leave(v): Knoten v wird rausgenommen
12.07.2012
VADS - Kapitel 6
18
Verteiltes Wörterbuch
Anforderungen:
1. Fairness: Jedes Speichermedium mit c% der
Kapazität speichert (erwartet) c% der Daten.
2. Effizienz: Die Speicherstrategie sollte zeit- und
speichereffizient sein.
3. Redundanz: Die Kopien eines Datums sollten
unterschiedlichen Speichern zugeordnet sein.
4. Adaptivität: Für jede Kapazitätsveränderung
von c% im System sollten nur O(c%) der Daten
umverteilt werden, um 1.-3. zu bewahren.
12.07.2012
VADS - Kapitel 6
19
Verteiltes Wörterbuch
Uniforme Speichersysteme: jeder Knoten
(Speicher) hat dieselbe Kapazität.
Nichtuniforme Speichersysteme: Kapazitäten
können beliebig unterschiedlich sein
Vorgestellte Strategien:
• Uniforme Systeme: konsistentes Hashing
• Nichtuniforme Speichersysteme: SHARE
• Combine & Split
12.07.2012
VADS - Kapitel 6
20
Konsistentes Hashing
Wähle zwei zufällige Hashfunktionen h, g
d
Daten
g:U→[0,1)
0
1
h:V→[0,1)
v
Speicher
Region, für die Speicher v zuständig ist
12.07.2012
VADS - Kapitel 6
21
Konsistentes Hashing
• V: aktuelle Knotenmenge
• succ(v): nächster Nachfolger von v in V bzgl.
Hashfunktion h (wobei [0,1) als Kreis gesehen wird)
• pred(v): nächster Vorgänger von v in V bzgl.
Hashfunktion h
Zuordnungsregeln:
• Eine Kopie pro Datum: Jeder Knoten v speichert alle
Daten d mit g(d)∈I(v) mit I(v)=[h(v), h(succ(v))).
• k>1 Kopien pro Datum: speichere jedes Datum d im
Knoten v oben und seinen k-1 nächsten Nachfolgern
bzgl. h
12.07.2012
VADS - Kapitel 6
22
Verteilte Hashtabelle
Fall 1: Server verwaltet Speicherknoten
insert, delete, lookup,
join, leave
12.07.2012
VADS - Kapitel 6
23
Verteilte Hashtabelle, Fall 1
Effiziente Datenstruktur für Server:
• Verwende interne Hashtabelle T mit m=Θ(n) Positionen.
• Jede Position T[i] mit i∈{0,…,m-1}
∈
ist für die Region
R(i)=[i/m, (i+1)/m) in [0,1) zuständig und speichert alle
Speicherknoten v mit I(v)∩R(i) ≠∅.
2
5
3
8
7
1
4
6
2
0
1
2,5
5,3
R(0)
R(1)
12.07.2012
3,8,7
7,1
1,4
VADS - Kapitel 6
4,6
6,2
2
24
Verteilte Hashtabelle, Fall 1
Effiziente Datenstruktur für Server:
• Jede Position T[i] mit i∈{0,…,m-1} ist für die Region
R(i)=[i/m, (i+1)/m) in [0,1) zuständig und speichert alle
Speicherknoten v mit I(v)∩R(i) ≠∅.
• Lookup(k): ermittle das R(i), das g(k) enthält, und
bestimme dasjenige v in T[i], dessen h(v) der nächste
Vorgänger von g(k) ist. Dieses v ist dann verantwortlich
für k und erhält die lookup Anfrage.
2,5
5,3
R(0)
R(1)
12.07.2012
3,8,7
7,1
1,4
VADS - Kapitel 6
4,6
6,2
2
25
Verteilte Hashtabelle, Fall 1
Effiziente Datenstruktur für Server:
• Jede Position T[i] mit i∈{0,…,m-1} ist für die Region
R(i)=[i/m, (i+1)/m) in [0,1) zuständig und speichert alle
Speicherknoten v mit I(v)∩R(i) ≠∅.
• Insert(d): ermittle zunächst wie bei Lookup dasjenige v,
das für d verantwortlich ist und leite dann Insert(d) an
dieses v weiter.
• Delete(k): analog
2,5
5,3
R(0)
R(1)
12.07.2012
3,8,7
7,1
1,4
VADS - Kapitel 6
4,6
6,2
2
26
Verteilte Hashtabelle, Fall 1
Effiziente Datenstruktur für Server:
• Verwende interne Hashtabelle T mit m=Θ(n) Positionen.
• Jede Position T[i] mit i∈{0,…,m-1}
∈
ist für die Region
R(i)=[i/m, (i+1)/m) in [0,1) zuständig und speichert alle
Speicherknoten v mit I(v)∩R(i)≠∅.
Einfach zu zeigen:
• T[i] enthält für m≥n erwartet konstant viele Elemente und
höchstens O(log n / log log n) mit hoher W.keit.
• D.h. Lookup(k) (die Ermittlung des zuständigen Knotens
für einen Schlüssel) benötigt erwartet konstante Zeit
12.07.2012
VADS - Kapitel 6
27
Verteilte Hashtabelle, Fall 1
Operationen:
• join(v): ermittle Intervall für v (durch Zugriff auf
T) und informiere Vorgänger von v, Daten, die
nun v gehören, zu v zu leiten
Beispiel: v=9
h(9)
2
5
3
8
7
1
4
6
2
0
1
2
5
3
8
7
1
0
12.07.2012
4
6
9
2
1
VADS - Kapitel 6
28
Verteilte Hashtabelle, Fall 1
Operationen:
• leave(v): errechne über T Knoten w, der Intervall
von v beerbt, und weise v an, alle Daten an w zu
leiten
Beispiel: v=8
2
5
3
8
7
1
4
6
2
0
1
2
5
3
7
1
0
12.07.2012
4
6
2
1
VADS - Kapitel 6
29
Verteilte Hashtabelle, Fall 1
Satz 6.2:
• Konsistentes Hashing ist effizient und redundant.
• Jeder Knoten speichert im Erwartungswert 1/n der Daten, d.h.
konsistentes Hashing ist fair.
• Bei Entfernung/Hinzufügung eines Speichers nur
Umplatzierung von erwartungsgemäß 1/n der Daten
Beweis:
Effizienz und Redundanz: siehe Protokoll
Fairness:
• Für jede Wahl von h gilt, dass Σv∈V |I(v)| = 1 und damit
Σv∈V E[|I(v)|] = 1 (E[]: Erwartungswert).
• Weiterhin gibt es für jedes Paar v,w∈V eine Bijektion auf der
Menge H der Hashfunktionen, f:H→H, so dass für alle h∈H
gilt, fass |I(v)| bzgl. h = |I(w)| bzgl. f(h). Daraus folgt, dass
E[|I(v)|] = E[|I(w)|].
• Die Kombinierung der beiden Gleichungen ergibt, dass
E[|I(v)|] = 1/n für alle v∈V.
12.07.2012
VADS - Kapitel 6
30
Verteilte Hashtabelle, Fall 1
Satz 6.2:
• Konsistentes Hashing ist effizient und redundant.
• Jeder Knoten speichert im Erwartungswert 1/n der Daten, d.h.
konsistentes Hashing ist fair.
• Bei Entfernung/Hinzufügung eines Speichers nur
Umplatzierung von erwartungsgemäß 1/n der Daten
Problem: Schwankung um 1/n hoch!
Lösung: verwende Θ(log n) viele Hashfunktionen für die Knoten
(d.h. jeder Knoten hat Θ(log n) Punkte in [0,1) ).
Aber stelle sicher, dass Redundanzforderung noch gilt!
12.07.2012
VADS - Kapitel 6
31
Verteilte Hashtabelle, Fall 1
Problem: Schwankung um 1/n hoch!
Alternative Lösung: Anpassung des eigenen Wertes
• Standard: x(v) = h(v)
• Jetzt kontinuierliche Updates:
x(pred(v)) + x(succ(v)) + h(v)/(c log n)
x(v) =
2 + 1/(c log n)
x(pred(v)) h(v)
x(succ(v))
Tendenz zu h(v)
x(v)
Damit Ausgleich der Intervallgrößen, aber noch nicht
analysiert!
12.07.2012
VADS - Kapitel 6
32
Verteilte Hashtabelle
Fall 2: verteiltes System
Jeder Knoten kann Anfragen (insert, delete,
lookup, join, leave) generieren.
12.07.2012
VADS - Kapitel 6
33
Verteilte Hashtabelle, Fall 2
Konsistentes Hashing: Zerlegung in zwei Probleme.
1. Abbildung der Daten auf die Knoten
2. Vernetzung der Knoten
12.07.2012
VADS - Kapitel 6
34
Verteilte Hashtabelle, Fall 2
Vernetzung der Knoten:
• Jedem Knoten v wird zufälliger Wert
id(v)∈[0,1) zugewiesen.
• Verwende dynamischen de Bruijn Graph, um
Knoten (hier im Kreis!) zu vernetzen.
0
12.07.2012
1
VADS - Kapitel 6
35
Verteilte Hashtabelle, Fall 2
Abbildung der Daten auf die Knoten:
• Verwende konsistentes Hashing
0
v
1
• insert(d): führe search(g(key(d))) im de Bruijn
Graph aus und speichere d im nächsten reellen
Vorgänger von g(key(d)) im de Bruijn Graph
12.07.2012
VADS - Kapitel 6
36
Verteilte Hashtabelle, Fall 2
Abbildung der Daten auf die Knoten:
• Verwende konsistentes Hashing
0
v
1
• delete(k): führe search(g(k)) im de Bruijn Graph
aus und lösche Datum d mit key(d)=k (falls da)
im nächsten reellen Vorgänger von g(k)
12.07.2012
VADS - Kapitel 6
37
Verteilte Hashtabelle, Fall 2
Abbildung der Daten auf die Knoten:
• Verwende konsistentes Hashing
0
v
1
• lookup(k): führe search(g(k)) im de Bruijn Graph
aus und liefere Datum d mit key(d)=k (falls da)
im nächsten reellen Vorgänger von g(k) zurück
12.07.2012
VADS - Kapitel 6
38
Verteilte Hashtabelle, Fall 2
Satz 6.3: Im stabilen Zustand ist der Zeitaufwand für die Operationen
• Insert(d): erwartet O(log n)
• Delete(k): erwartet O(log n)
• Lookup(k): erwartet O(log n)
• Join(v): O(1) (verbinde v mit beliebigem Knoten im de Bruijn Graph,
Rest durch Build-deBruijn)
• Leave(v): O(1) (verlasse de Bruijn Graph, Rest durch Build-deBruijn)
Beweis:
Folgt aus Analyse des de Bruijn Graphen
Mögliche Verbesserungen:
• im stabilen Zustand Join über Lookup realisieren, um Knoten gleich
richtig zu platzieren
• Jeden (virtuellen) Knoten mit den zwei nächsten Vorgängern und
Nachfolgern im Ring verbinden, um Leave schneller zu reparieren
12.07.2012
VADS - Kapitel 6
39
Verteiltes Wörterbuch
Uniforme Speichersysteme: jeder Knoten
(Speicher) hat dieselbe Kapazität.
Nichtuniforme Speichersysteme: Kapazitäten
können beliebig unterschiedlich sein
Vorgestellte Strategien:
• Uniforme Systeme: konsistentes Hashing
• Nichtuniforme Speichersysteme: SHARE
• Combine & Split
12.07.2012
VADS - Kapitel 6
40
SHARE
Situation hier: wir haben Knoten mit beliebigen relativen Kapazitäten c1,…,cn, d.h.
∑i ci = 1.
Problem: konsistentes Hashing funktioniert
nicht gut, da Knoten nicht einfach in
virtuelle Knoten gleicher Kapazität
aufgeteilt werden können.
Lösung: SHARE
12.07.2012
VADS - Kapitel 6
41
SHARE
Datenabbildung: wie bei konsistentem Hashing
d
Daten
g:U→[0,1)
0
1
Zuordnung der Speicher: andere Strategie
1
12.07.2012
2
3
VADS - Kapitel 6
4
5
6
42
SHARE
Zuordnung zu Speichern: zweistufiges Verfahren.
1. Stufe: Jedem Knoten v wird ein Intervall
I(v)⊆[0,1) der Länge s⋅cv zugeordnet, wobei
s=Θ(log n) ein fester Stretch-Faktor ist. Die
Startpunkte der Intervalle sind durch eine
Hashfunktion h:V→[0,1) gegeben.
0
1
1
12.07.2012
2
3
4
VADS - Kapitel 6
5
6
43
SHARE
Zuordnung zu Speichern: zweistufiges Verfahren.
1. Stufe: Jedem Datum d wird mittels einer
Hashfunktion g:U→[0,1) ein Punkt x∈[0,1)
zugewiesen und die Multimenge Vx aller
Knoten v bestimmt mit x∈I(v) (für |I(v)|>1 zählt
v sooft wie I(v) x enthält).
Vx={1,4}
x
0
1
12.07.2012
2
3
4
VADS - Kapitel 6
1
5
6
44
SHARE
Zuordnung zu Speichern: zweistufiges Verfahren.
2. Stufe: Für Datum d wird mittels konsistentem
Hashing mit Hashfunktionen h’ und g’ (die für
alle Punkte x∈[0,1) gleich sind) ermittelt,
welcher Knoten in Vx Datum d speichert.
Vx={1,4}
x
0
1
12.07.2012
2
3
4
VADS - Kapitel 6
1
5
6
45
SHARE
Realisierung:
1
2
4
3
insert, delete, lookup,
join, leave und
Kapazitätsveränderungen
12.07.2012
VADS - Kapitel 6
46
SHARE
Effiziente Datenstruktur im Server:
• 1. Stufe: verwende Hashtabelle wie für konsistentes
Hashing, um alle möglichen Multimengen für alle
Bereiche [i/m,(i+1)/m) zu speichern.
• 2. Stufe: verwende separate Hashtabelle der Größe Θ(k)
für jede mögliche Multimenge aus der 1. Stufe mit k
Elementen (es gibt maximal 2n Multimengen, da es nur
n Intervalle mit jeweils 2 Endpunkten gibt)
Laufzeit:
• 1. Stufe: O(1) erw. Zeit zur Bestimmung der Multimenge
• 2. Stufe: O(1) erw. Zeit zur Bestimmung des Knotens
12.07.2012
VADS - Kapitel 6
47
SHARE
Satz 6.4:
1. SHARE ist effizient.
2. Jeder Knoten i speichert im Erwartungswert ciAnteil der Daten, d.h. SHARE ist fair.
3. Bei jeder relativen Kapazitätsveränderung um
c∈[0,1)
∈
nur Umplatzierung eines erwarteten
c-Anteils der Daten notwendig
Problem: Redundanz nicht einfach zu garantieren!
Lösung: SPREAD (recht komplex)
12.07.2012
VADS - Kapitel 6
48
SHARE
Beweis:
Punkt 2:
• s=Θ(log n): Da dann Σv∈V |I(v)|=s, ist die erwartete
Anzahl Intervalle über jeden Punkt in [0,1) gleich s,
und Abweichungen davon sind klein mit hoher
W.keit falls s genügend groß.
• Knoten i hat Intervall der Länge s⋅ci
• Erwarteter Anteil Daten in Knoten i:
(s⋅ci) ⋅ (1/s) = ci
Phase 1 Phase 2
12.07.2012
VADS - Kapitel 6
49
SHARE
Punkt 3:
• Betrachte Kapazitätsveränderung von (c1,…,cn)
nach (c’1,…,c’n)
• Differenz: c = ∑i |ci-c’i|
• Optimale Strategie, die Fairness sicherstellt:
Mindestaufwand c/2
• SHARE: Intervalldifferenz ∑i |s(ci-c’i)| = s⋅c
• Erwarteter Anteil umverteilter Daten:
(s⋅c) / s = c, also maximal doppelt so viel wie
optimal
12.07.2012
VADS - Kapitel 6
50
SHARE
Gibt es auch eine effiziente verteilte Variante?
Jeder Knoten kann Anfragen (insert, delete,
lookup, join, leave) generieren und Kapazität
beliebig verändern.
12.07.2012
VADS - Kapitel 6
51
Verteiltes Wörterbuch
Uniforme Speichersysteme: jeder Knoten
(Speicher) hat dieselbe Kapazität.
Nichtuniforme Speichersysteme: Kapazitäten
können beliebig unterschiedlich sein
Vorgestellte Strategien:
• Uniforme Systeme: konsistentes Hashing
• Nichtuniforme Speichersysteme: SHARE
• Combine & Split
12.07.2012
VADS - Kapitel 6
52
Verteilte Hashtabelle
Probleme bei vielen Anfragen auf dasselbe Datum:
Subjekt, das Datum speichert, wird überlastet.
Lösung: Combine & Split
12.07.2012
VADS - Kapitel 6
53
Verteilte Hashtabelle
Combine & Split:
• Treffen sich zwei lookup Anfragen zu demselben Datum, werden sie
zu einer kombiniert, das als neues Rückantwortsziel den Knoten v
wählt, in dem die Anfragen kombiniert worden sind. v merkt sich
dann die kombinierten Anfragen, so dass diese bei Erhalt des
Datums bedient werden können.
x
Anfragen
x
x
x
x
x
Antworten
x
x
12.07.2012
…
VADS - Kapitel 6
54
Verteilte Hashtabelle
Combine & Split:
• Treffen sich zwei insert oder delete Anfragen zu demselben Datum,
werden sie zu einer kombiniert. Bei insert gewinnt dabei eine
beliebige der beiden Anfragen.
x
x
…
x
x
Beobachtung: Mit der Combine & Split Regel ist die Congestion in der
Größenordnung der Congestion, falls nur Anfragen auf
verschiedene Daten unterwegs sind.
12.07.2012
VADS - Kapitel 6
55
Übersicht
•
•
•
•
•
Verteilte Hashtabelle
Verteilte Suchstruktur
Verteilter Stack
Verteilte Queue
Verteilter Heap
12.07.2012
VADS - Kapitel 6
56
Präfix Suche
• Alle Schlüssel kodiert als binäre Folgen {0,1}W
• Präfix eines Schlüssels x∈{0,1}W: eine beliebige
Teilfolge von x, die mit dem ersten Bit von x
startet (z.B. ist 101 ein Präfix von 10110100)
Problem: finde für einen Schlüssel x∈{0,1}W einen
Schlüssel y∈S mit größtem gemeinsamen Präfix
Lösung: Trie Hashing
12.07.2012
VADS - Kapitel 6
57
Trie
Ein Trie ist ein Suchbaum über einem Alphabet Σ, der
die folgenden Eigenschaften erfüllt:
• Jede Baumkante hat einen Label c∈Σ
• Jeder Schlüssel x∈Σk ist von der Wurzel des Tries über
den eindeutigen Pfad der Länge k zu erreichen, dessen
Kantenlabel zusammen x ergeben.
Hier: alle Schlüssel aus {0,1}W
Beispiel:
(0,2,3,5,6) mit W=3 ergibt (000,010,011,101,110)
12.07.2012
VADS - Kapitel 6
58
Trie
Trie aus Beispielzahlen:
0
0
0
1
0
0
000
010
12.07.2012
1
1
1
1
011
101
VADS - Kapitel 6
0
110
59
Trie
Präfixsuche für Zahl 4 (4 entspricht 100):
0
0
1
0
1
0
0
000
010
1
1
1
011
101
0
110
Ausgabe: 5 (größter gem. Präfix)
12.07.2012
VADS - Kapitel 6
60
Trie
Insert(1) (1 entspricht 001):
0
0
0
000
12.07.2012
1
001
1
0
1
0
010
1
1
1
011
101
VADS - Kapitel 6
0
110
61
Trie
Delete(5):
0
0
0
000
12.07.2012
1
001
1
0
1
0
010
1
1
1
011
101
VADS - Kapitel 6
0
110
62
Patricia Trie
Probleme:
• Präfixsuche im Trie mit Schlüsseln aus x∈{0,1}W
kann Θ(W) Zeit dauern.
• Insert und delete benötigen bis zu Θ(W)
Restrukturierungen
Verbesserung: verwende Patricia Tries
Ein Patricia Trie ist ein Trie, in dem alle Knotenketten (d.h. Folgen von Knoten mit Grad 1) zu
einer Kante verschmolzen werden.
12.07.2012
VADS - Kapitel 6
63
Trie
Trie aus Beispielzahlen:
0
0
0
1
0
0
000
010
12.07.2012
1
1
1
1
011
101
VADS - Kapitel 6
0
110
64
Patricia Trie
Jeder Baumknoten hat Grad 2.
0
1
1
00
01
0
000
12.07.2012
010
10
1
011
VADS - Kapitel 6
101
110
65
Patricia Trie
Search(4):
0
1
1
00
01
0
000
12.07.2012
010
10
1
011
VADS - Kapitel 6
101
110
66
Patricia Trie
Insert(1):
0
0
1
1
00
0
000
12.07.2012
01
1
001
0
010
10
1
011
VADS - Kapitel 6
101
110
67
Patricia Trie
Delete(5):
0
0
1
110
1
01
0
000
12.07.2012
1
001
0
010
10
1
011
VADS - Kapitel 6
101
110
68
Patricia Trie
• Search, insert und delete wie im einfachen
binären Suchbaum, nur dass wir Labels an
den Kanten haben.
• Suchzeit immer noch O(W), aber
Restrukturierungsaufwand nur noch O(1)
Idee: Um Suchzeit zu verringern, hashen wir
Patricia Trie auf [0,1) (damit konsistentes
Hashing oder SHARE anwendbar).
12.07.2012
VADS - Kapitel 6
69
Patricia Trie
Hashing auf [0,1):
• Knotenlabel: Konkatenation der Kantenlabel von Wurzel
• Jeder Knoten wird gemäß seines Knotenlabels in [0,1)
gehasht.
0
10
010
g(010)
0
1
• Dann kann auf jeden Patricia Knoten mit einer DHT-Anfrage
zugegriffen werden, falls sein Label bekannt.
12.07.2012
VADS - Kapitel 6
70
Patricia Trie
Hashing auf [0,1):
• Knotenlabel: Konkatenation der Kantenlabel von Wurzel
• Jeder Knoten wird gemäß seines Knotenlabels in [0,1)
gehasht.
0
1
Problem: Binäre Suche über Knotenlabel wäre dann denkbar für
Zeitreduktion O(W) → O(log W), aber noch nicht machbar.
12.07.2012
VADS - Kapitel 6
71
Patricia Trie
Hashing auf [0,1):
• Knotenlabel: Konkatenation der Kantenlabel von Wurzel
• Jeder Knoten wird gemäß seines Knotenlabels in [0,1)
gehasht.
0
1
Lösung: Füge geeignete Stützknoten ein (msd-Knoten).
12.07.2012
VADS - Kapitel 6
72
Trie Hashing
• Für eine Bitfolge x sei |x| die Länge von x.
• Für einen Baumknoten v sei b(v) die konkatenierte
Bitfolge der Kanten des eindeutigen Weges von der
Wurzel zu v (d.h. der gem. Präfix aller Elemente unter v).
• msd(f,f´) für zwei Bitfolgen 0*◦f und 0*◦f´: höchstes Bit,
in dem sich 0*◦f und 0*◦f´ unterscheiden (0*=0000…).
• Betrachte eine Bitfolge b mit Binärdarstellung von |b|
gleich (xk,…,x0) . Sei b’ ein Präfix von b.
Die msd-Folge m(b’,b) von b’ und b ist das Präfix von b
der Länge ∑i=jk xi 2i mit j=msd(|b|,|b’|).
Beispiel: Betrachte b=01101001010 und b’=011010. Dann
ist |b|=11 oder binär 1011 und |b’|=6 oder binär 110, d.h.
msd(|b|,|b’|)=3. Also ist von m(b’,b)= 01101001.
12.07.2012
VADS - Kapitel 6
73
Trie Hashing
Zentrale Idee: Wir ersetzen jede Kante e={v,w} im
Patricia Trie durch zwei Kanten {v,u} und {u,w}
mit b(u)=m(b(v),b(w)) und bilden resultierenden
Patricia Trie auf [0,1) ab.
v
v
p
w
12.07.2012
p1
u
p1 ∘ p2 = p
p2
msd-Knoten
von v und w
VADS - Kapitel 6
w
74
Trie Hashing
p’
v p
g(b(v))
0
12.07.2012
p
VADS - Kapitel 6
p’
1
75
Trie Hashing
Datenstruktur:
Jeder Hasheintrag zu einem Baumknoten v speichert:
1. Bitfolge b(v) zu v
2. Schlüssel key(v) eines Elements e, falls v Knoten im
Original Patricia Trie ist (für Suchergebnis)
3. Bitfolgen px(v) der Kanten bzgl. nächstem Bit x∈{0,1}
∈
zu
Kindern von v (für Suche)
4. Bitfolge p-(v) zum Vaterknoten (für Restrukturierung)
Jeder Hasheintrag zu einem Element e speichert:
1. Schlüssel von e
2. Ort des Schlüssels von e im Baum (siehe 2. oben)
12.07.2012
VADS - Kapitel 6
76
Trie Hashing
Beispiel:
p-(u)=101
b(u)=10110101
u
key(u)=101101010010011
p1(u)=10
p0(u)=0010
p1(v)=0
w
12.07.2012
v
b(v)=101101010010
b(w)=1011010100100
VADS - Kapitel 6
77
Trie Hashing
Wir vergessen zunächst die Suchproblematik
und illustrieren insert und delete.
k3
k1
k4
k2
k1
12.07.2012
k2
k3
VADS - Kapitel 6
k4
∞
78
Trie Hashing
Forderung: jedes Element in exakt einem inneren
Knoten vom Patricia Trie. (Möglich mit Dummy ∞.)
k3
k1
k4
k2
k1
12.07.2012
k2
k3
VADS - Kapitel 6
k4
∞
79
Trie Hashing
Insert(e) mit key(e)=k5: wie im bin. Suchbaum
k3
k1
k4
k5
k1
12.07.2012
k2
k5
k2
k3
VADS - Kapitel 6
k4
∞
80
Trie Hashing
Delete(k3): wie im binären Suchbaum
k23
k1
k4
k2
k1
12.07.2012
k2
k3
VADS - Kapitel 6
k4
∞
81
Trie Hashing
Search(x): (W Zweierpotenz)
Phase 1: binäre Suche über msd-Knoten
0
W/2
3W/4
W
12.07.2012
x
VADS - Kapitel 6
y
82
Trie Hashing
Search(x): (W Zweierpotenz)
Phase 2: lies Schlüssel aus Baumknoten
Fall 1:
Ende Phase 1
Antwort: y
y
z
x
12.07.2012
y
z
VADS - Kapitel 6
83
Trie Hashing
Search(x): (W Zweierpotenz)
Phase 2: lies Schlüssel aus Baumknoten
Fall 2:
Ende Phase 1
Antwort: z
y
z
y
12.07.2012
x
z
VADS - Kapitel 6
84
Trie Hashing
• x∈{0,1}W habe Darstellung (x1,…,xW)
• Hashfunktion: h:U→[0,1)
search(x):
// gleich gefunden, dann fertig
if key(T[h(x)])=x then return T[h(x)]
// Phase 1: binäre Suche auf x
s:=⌊log W⌋; k:=0; v:=T[h(ε)]; p:=px1(v) // v: Wurzel des Patricia Tries
while s >= 0 do
// gibt es Element mit Präfix (x1,…,xk+2s) ?
if (x1,…,xk+2s) = b(T[h(x1,…,xk+2s)]) // (msd-)Knoten existiert
then k:=k+2s; v:=T[h(x1,…,xk)]; p:= (x1,…,xk) ∘ pxk+1(v)
else if (x1,…,xk+2s) ist Präfix von p
// Kante aus v deckt (x1,…,xk+2s) ab
then k:=k+2s
s:=s-1
// weiter mit Phase 2…
12.07.2012
VADS - Kapitel 6
85
Trie Hashing
search(x): (Fortsetzung)
// Phase 2: Laufe zu Knoten mit größtem Präfix
while b(v) ist Präfix von (x1,…,xk) do
if pxk+1(v) existiert then
k:=k+|pxk+1(v)|
v:=T[h(b(v) ∘ pxk+1(v))]
else
k:=k+|pxk+1(v)|
v:=T[h(b(v) ∘ pxk+1(v))]
if v ist msd-Knoten then
v:=T[h(b(v) ∘ p)] für Bitfolge p aus v
return key(v)
12.07.2012
VADS - Kapitel 6
86
Trie Hashing
Korrektheit von Phase 1:
• Sei p der größte gemeinsame Präfix von x und
einem Element y∈S
∈ und sei |p|=(zk,…,z0).
• Patricia Trie enthält Route für Präfix p
• Sei v letzter Knoten auf Route bis p
• Fall 1: v ist Patricia Knoten
v
0
12.07.2012
|p|
Binärdarstellung von |b(v)| habe Einsen
an den Positionen i1,i2,… (i1 maximal)
VADS - Kapitel 6
87
Trie Hashing
Korrektheit von Phase 1:
• Sei p der größte gemeinsame Präfix von x und
einem Element y∈S
∈ und sei |p|=(zk,…,z0).
• Patricia Trie enthält Route für Präfix p
• Sei v letzter Knoten auf Route bis p
• Fall 1: v ist Patricia Knoten
w
0
12.07.2012
v
|b(w)|<2i1
|p|
msd-Knoten muss bei 2i1 existieren,
wird bei binärer Suche gefunden
VADS - Kapitel 6
88
Trie Hashing
Korrektheit von Phase 1:
• Sei p der größte gemeinsame Präfix von x und
einem Element y∈S
∈ und sei |p|=(zk,…,z0).
• Patricia Trie enthält Route für Präfix p
• Sei v letzter Knoten auf Route bis p
• Fall 1: v ist Patricia Knoten
w
2i1
12.07.2012
pw
u
v
|p|
2i1+2i2
a) kein msd-Knoten bei 2i1+2i2 : nur dann, wenn
kein Patricia-Knoten u mit 2i1<|b(u)|≤2i1+2i2,
aber das wird durch pw erkannt und abgedeckt
VADS - Kapitel 6
89
Trie Hashing
Korrektheit von Phase 1:
• Sei p der größte gemeinsame Präfix von x und
einem Element y∈S
∈ und sei |p|=(zk,…,z0).
• Patricia Trie enthält Route für Präfix p
• Sei v letzter Knoten auf Route bis p
• Fall 1: v ist Patricia Knoten
v
2i1
12.07.2012
|p|
<2i1+2i2
b) msd-Knoten bei 2i1+2i2: wird durch binäre
Suche gefunden
VADS - Kapitel 6
90
Trie Hashing
Korrektheit von Phase 1:
• Sei p der größte gemeinsame Präfix von x und
einem Element y∈S
∈ und sei |p|=(zk,…,z0).
• Patricia Trie enthält Route für Präfix p
• Sei v letzter Knoten auf Route bis p
• Fall 1: v ist Patricia Knoten
v
∑j 2ij
usw. bis msd-Knoten vor v gefunden
12.07.2012
VADS - Kapitel 6
|p|
91
Trie Hashing
Korrektheit von Phase 1:
• Sei p der größte gemeinsame Präfix von x und
einem Element y∈S
∈ und sei |p|=(zk,…,z0).
• Patricia Trie enthält Route für Präfix p
• Sei v letzter Knoten auf Route bis p
• Fall 1: v ist Patricia Knoten
w
∑j 2ij
pw
v
|p|
Durch Beachtung von pw im Algorithmus wird dann
auch v gefunden.
12.07.2012
VADS - Kapitel 6
92
Trie Hashing
Korrektheit von Phase 1:
• Sei p der größte gemeinsame Präfix von x und
einem Element y∈S
∈ und sei |p|=(zk,…,z0).
• Patricia Trie enthält Route für Präfix p
• Sei v letzter Knoten auf Route bis p
• Fall 2: v ist msd-Knoten
v
|p|
0
In diesem Fall wird v gefunden (Argumente wie für Fall 1)
12.07.2012
VADS - Kapitel 6
93
Trie Hashing
Aufwand für search:
• Phase 1 (binäre Suche): O(log W) Lesezugriffe auf DHT
• Phase 2 (entlang Patricia Trie): O(1) Lesezugriffe auf DHT
Insgesamt O(log W) Lesezugriffe auf DHT.
Aufwand für insert:
• O(log W) Lesezugriffe auf DHT für search-Operation
• O(1) Restrukturierungen im Patricia Trie
Also O(log W) Lese- und O(1) Schreibzugriffe auf DHT
Aufwand von delete: O(1) Lese- und Schreibzugriffe auf DHT
(nur Restrukturierung)
12.07.2012
VADS - Kapitel 6
94
Trie Hashing
Datenuniversum: U
• Wortgröße: W=⌈log |U|⌉
•
•
Anzahl Lesezugriffe (search, insert):
O(log W) = O(log log |U|)
Anzahl Schreibzugriffe (insert, delete):
O(1)
Beispiel: U={a,…,z}10
Anzahl Zugriffe ~6
12.07.2012
VADS - Kapitel 6
95
Trie Hashing
Probleme bei vielen Anfragen auf dieselben
Patricia Trie Knoten:
Subjekt, das Knoten speichert, wird überlastet.
Auch hier Lösung: Combine & Split
12.07.2012
VADS - Kapitel 6
96
Nachfolgersuche
• Alle Schlüssel kodiert als binäre Folgen {0,1}W
• S: gegebene Schlüsselmenge
• Nächster Nachfolger eines Schlüssels x∈{0,1}W: der
lexikographisch nächste Schlüssel von x in S
Problem: finde für einen Schlüssel x∈{0,1}W den
nächsten Nachfolger y∈S
Einfache Lösung: auch hier Trie Hashing, aber wir
verwenden nur normalen Patricia Trie (ohne msdKnoten)
12.07.2012
VADS - Kapitel 6
97
Nachfolgersuche
Search(4) ergibt 5 (bzw. 101)
0
1
1
00
01
0
000
12.07.2012
010
10
1
011
VADS - Kapitel 6
101
110
98
Nachfolgersuche
Aufwand für search:
• Suche entlang Patricia Trie: im worst case O(W) Lesezugriffe
auf DHT
Aufwand für insert:
• O(W) Lesezugriffe auf DHT für search-Operation
• O(1) Restrukturierungen im Patricia Trie
Also O(W) Lese- und O(1) Schreibzugriffe auf DHT
Aufwand von delete: O(1) Lese- und Schreibzugriffe auf DHT
(nur Restrukturierung)
Kann Suche nach nächstem Nachfolger beschleunigt werden?
12.07.2012
VADS - Kapitel 6
99
Nachfolgersuche
Kann Suche nach nächstem Nachfolger beschleunigt werden?
•
Wir nutzten Patricia Trie mit msd-Knoten mit zusätzlichen Pointern
•
Jeder Original Patricia Knoten v speichert zusätzlich die Bitfolge rmin
des kleinsten Knoten im rechten Subtrie von v. Damit bekommt jedes
Blatt w maximal einen weiteren Patricia Knoten zugewiesen, nämlich
den kleinsten gemeinsamen Vorfahr von w und seinem nächsten
Vorgänger. Die Wurzel merkt sich zusätzlich das minimale Blatt.
•
Alle Blätter bilden eine doppelt verkettete Liste.
12.07.2012
VADS - Kapitel 6
100
Nachfolgersuche
•
Sei u Knoten, der in Phase 1 zurückgegeben wird. b(u) ist Präfix von x.
•
Sei v Knoten, der in Phase 2 zurückgegeben wird. key(v) und b(v) haben
längsten gemeinsamen Präfix mit x.
•
Suche dann über binäre Suche nach Vorfahr w von v, so dass rmin von w
der Nachfolger von x ist.
w
u
Antwort: z
v
x
12.07.2012
VADS - Kapitel 6
y
z
101
Nachfolgersuche
•
Sei u Knoten, der in Phase 1 zurückgegeben wird. b(u) ist Präfix von x.
•
Sei v Knoten, der in Phase 2 zurückgegeben wird. key(v) und b(v) haben
längsten gemeinsamen Präfix mit x.
•
Suche dann über binäre Suche nach Vorfahr w von v, so dass rmin von w
der Nachfolger von x ist.
w
u
Antwort: z
v
y
12.07.2012
x
VADS - Kapitel 6
z
102
Nachfolgersuche
•
Sei u Knoten, der in Phase 1 zurückgegeben wird. b(u) ist Präfix von x.
•
Sei v Knoten, der in Phase 2 zurückgegeben wird. key(v) und b(v) haben
längsten gemeinsamen Präfix mit x.
•
Suche dann über binäre Suche nach Vorfahr w von v, so dass rmin von w
der Nachfolger von x ist.
w
u
Antwort: z
v
y
12.07.2012
x
z
VADS - Kapitel 6
103
Nachfolgersuche
•
Sei u Knoten, der in Phase 1 zurückgegeben wird. b(u) ist Präfix von x.
•
Sei v Knoten, der in Phase 2 zurückgegeben wird. key(v) und b(v) haben
längsten gemeinsamen Präfix mit x.
•
Suche dann über binäre Suche nach Vorfahr w von v, so dass rmin von w
der Nachfolger von x ist.
w
u
Antwort: ∞
v
12.07.2012
VADS - Kapitel 6
y
x
∞
104
Nachfolgersuche
•
Sei u Knoten, der in Phase 1 zurückgegeben wird. b(u) ist Präfix von x.
•
Sei v Knoten, der in Phase 2 zurückgegeben wird. key(v) und b(v) haben
längsten gemeinsamen Präfix mit x.
•
Suche dann über binäre Suche nach Vorfahr w von v, so dass rmin von w
der Nachfolger von x ist.
w
u
Antwort: y
v
x
12.07.2012
y
VADS - Kapitel 6
105
Nachfolgersuche
•
Sei v Knoten, der in Phase 2 zurückgegeben wird. key(v) und b(v) haben
längsten gemeinsamen Präfix mit x.
•
Binäre Suche bei w nach unten: z < x < z´ bzw. z´<x<z
w
v
z
12.07.2012
x
VADS - Kapitel 6
z´
106
Nachfolgersuche
•
Sei v Knoten, der in Phase 2 zurückgegeben wird. key(v) und b(v) haben
längsten gemeinsamen Präfix mit x.
•
Binäre Suche bei w nach oben: x<z, x<z´ bzw. x>z´, x>z
w
v
x
12.07.2012
z
VADS - Kapitel 6
z´
107
Nachfolgersuche
Aufwand für search:
• Binäre Suche im Patricia Trie: im worst case O(log W) Lesezugriffe
auf DHT
Aufwand für insert und delete:
• O(log W) Lesezugriffe auf DHT für search-Operation
• O(1) Restrukturierungen im Patricia Trie
(auf jedes Blatt zeigen maximal ein zusätzlicher Pointer)
Also O(log W) Lese- und O(1) Schreibzugriffe auf DHT
Übung: gib Details der insert und delete Operationen an.
12.07.2012
VADS - Kapitel 6
108
Übersicht
•
•
•
•
•
Verteilte Hashtabelle
Verteilte Suchstruktur
Verteilter Stack
Verteilte Queue
Verteilter Heap
12.07.2012
VADS - Kapitel 6
109
Konventioneller Stack
Ein Stack S unterstützt folgende Operationen:
• push(S,x): legt Element x oben auf dem
Stack ab.
• pop(S): holt das oberste Element aus dem
Stack S heraus und gibt es zurück
D.h. ein Stack S implementiert die LIFO-Regel
(LIFO: last in first out).
12.07.2012
VADS - Kapitel 6
110
Verteilter Stack
Viele Prozesse agieren auf Stack:
12.07.2012
VADS - Kapitel 6
111
Verteilter Stack
Probleme:
• Speicherung des Stacks
• Realisierung von push und pop
12.07.2012
VADS - Kapitel 6
112
Verteilter Stack
Speicherung des Stacks:
• Jedes Element x besitzt eindeutige
Position pos(x)≥1 im Stack (das oberste
hat die größte Position).
• Verwende eine verteilte Hashtabelle, um
die Elemente x gleichmäßig mit
Schlüsselwert pos(x) zu speichern.
• Topologie für Hashtabelle: dynamischer
der Bruijn Graph.
12.07.2012
VADS - Kapitel 6
113
Verteilter Stack
Realisierung von push(S,x):
1. Stelle push(S,1)-Anfrage, um eine Nummer pos zu erhalten.
2. Führe insert(pos,x) auf der verteilten Hashtabelle aus, um x
unter pos zu speichern.
Realisierung von pop(S):
1. Stelle pop(S,1)-Anfrage, um eine Nummer pos zu erhalten.
2. Führe delete(pos) auf der verteilten Hashtabelle aus, um das
unter pos gespeicherte Element x zu löschen und zu
erhalten.
Noch zu klären: Punkt 1.
Hier kommt uns die de Bruijn Topologie zu Hilfe.
12.07.2012
VADS - Kapitel 6
114
Verteilter Stack
Realisierung von push(S,1):
• Schicke alle push(S,1) Anfragen zu Punkt 0 im [0,1)-Raum mit Hilfe des de
Bruijn Routings.
0
•
•
•
•
1
Der für Punkt 0 zuständige Knoten v0 merkt sich einen Zähler pos.
Wenn sich zwei push(S,i) und push(S,j) Anfragen in einem Knoten v treffen,
kombiniere diese zu push(S,i+j) mit Rückadresse v (und einer internen
Nummer, über die v die ursprünglichen Anfragen speichert, um sie bei einer
Rückantwort zu bedienen).
Erreicht eine push(S,i) Anfrage v0, dann schickt v0 das Intervall
[pos+1,pos+i] an die Rückadresse und setzt pos:=pos+i.
Erhält ein Knoten v ein Intervall [pos,pos+i+j-1], das zu zwei push(S,i) und
push(S,j) Anfragen gehört, schickt v das Intervall [pos,pos+i-1] an die
Rückadresse von push(S,i) und das Intervall [pos+i,pos+i+j-1] an die
Rückadresse von push(S,j).
12.07.2012
VADS - Kapitel 6
115
Verteilter Stack
Realisierung von pop(S,1):
• Schicke alle pop(S,1) Anfragen zu Punkt 0 im [0,1)-Raum mit Hilfe
des de Bruijn Routings.
• Der für Punkt 0 zuständige Knoten v0 merkt sich einen Zähler pos.
• Wenn sich zwei pop(S,i) und pop(S,j) Anfragen in einem Knoten v
treffen, kombiniere diese zu pop(S,i+j) mit Rückadresse v (und einer
internen Nummer).
• Erreicht eine pop(S,i) Anfrage v0, dann schickt v0 das Intervall
[max{1,pos-i+1},pos] zurück und setzt pos:=max{0,pos-i}.
• Erhält ein Knoten v ein Intervall [pos,pos+i+j-1], das zu zwei pop(S,i)
und pop(S,j) Anfragen gehört, schickt v das Intervall [pos,pos+i-1]
an die Rückadresse von pop(S,i) und das Intervall [pos+i,pos+i+j-1]
an die Rückadresse von pop(S,j). (Ist das Intervall kleiner als i+j,
wird entsprechend bei den zwei Intervallen gekürzt. Ist eines dieser
beiden Intervalle leer, heißt das, dass keine Elemente im Stack für
diesen pop Befehl zur Verfügung stehen.)
12.07.2012
VADS - Kapitel 6
116
Verteilter Stack
Satz 6.4: Der verteilte Stack benötigt (mit einer verteilten
Hashtabelle auf Basis eines dynamischen de Bruijn
Netzwerks) für die Operationen
• push(S,x): erwartete Zeit O(log n)
• pop(S): erwartete Zeit O(log n)
Verwaltung mehrerer Stacks in derselben Hashtabelle:
weise jedem Stack statt Punkt 0 einen (pseudo-)
zufälligen Punkt in [0,1) zu.
12.07.2012
VADS - Kapitel 6
117
Verteilter Stack
Lokale Konsistenz:
• quellorientiert:
- einfachste Strategie: jeder Knoten wartet erst ab, dass die aktuelle
Operation beendet ist, bevor er die nächste initiiert
- Übung: geht es auch besser?
• routingorientiert:
Über periodische Wellenfronten, die von den Knoten mit minimaler ID (für
Routing von Zuweisungen) und maximaler ID (für Routing von Anfragen)
gestartet werden und über lineare und de Bruijn Kanten propagiert werden.
Beispiel: Wellenfront mit zwei Bits initiiert vom Knoten mit max. ID.
01 0
0 1
1 0
12.07.2012
1
0
1
0
1
0
1
0
1
VADS - Kapitel 6
1
Zeit
118
Übersicht
•
•
•
•
•
Verteilte Hashtabelle
Verteilte Suchstruktur
Verteilter Stack
Verteilte Queue
Verteilter Heap
12.07.2012
VADS - Kapitel 6
119
Konventionelle Queue
Eine Queue Q unterstützt folgende Operationen:
• enqueue(Q,x): fügt Element x hinten an die Queue
Q an.
• dequeue(Q): holt das vorderste Element aus der
Queue Q heraus und gibt es zurück
D.h. eine Queue Q implementiert die FIFO-Regel
(FIFO: first in first out).
12.07.2012
VADS - Kapitel 6
120
Verteilte Queue
Viele Subjekte agieren auf Queue:
12.07.2012
VADS - Kapitel 6
121
Verteilte Queue
Probleme:
• Speicherung der Queue
• Realisierung von enqueue und dequeue
12.07.2012
VADS - Kapitel 6
122
Verteilte Queue
Speicherung der Queue:
• Jedes Element x besitzt eindeutige Position
pos(x)≥1 in der Queue (das vorderste hat die
kleinste und das hinterste die größte
Position).
• Verwende eine verteilte Hashtabelle, um die
Elemente x gleichmäßig mit Schlüsselwert
pos(x) zu speichern.
• Topologie für Hashtabelle: dynamischer der
Bruijn Graph.
12.07.2012
VADS - Kapitel 6
123
Verteilte Queue
Realisierung von enqueue(Q,x):
1. Stelle enqueue(Q,1)-Anfrage, um eine Nummer pos zu
erhalten.
2. Führe insert(pos,x) auf der verteilten Hashtabelle aus, um x
unter pos zu speichern.
Realisierung von dequeue(Q):
1. Stelle dequeue(S,1)-Anfrage, um eine Nummer pos zu
erhalten.
2. Führe delete(pos) auf der verteilten Hashtabelle aus, um das
unter pos gespeicherte Element x zu löschen und zu
erhalten.
Noch zu klären: Punkt 1.
Hier kommt uns die de Bruijn Topologie zu Hilfe.
12.07.2012
VADS - Kapitel 6
124
Verteilte Queue
Realisierung von enqueue(Q,1) und dequeue(Q,1):
• Schicke alle enqueue und dequeue Anfragen zu Punkt 0 im [0,1)Raum mit Hilfe des de Bruijn Routings.
• Der für Punkt 0 zuständige Knoten v0 merkt sich zwei Zähler first
und last. first speichert die Position des ersten und last die Position
des letzten Elements in Q. (Da der Wertebereich {1,…,m} der
möglichen Positionen endlich ist, werden first und last im ModuloRing aktualisiert. Wir können aber annehmen, dass m sehr groß ist.)
• Wenn sich zwei enqueue oder dequeue Anfragen in einem Knoten v
treffen, kombiniere diese wie die push und pull Anfragen im Stack.
• Erreicht eine enqueue(Q,i) Anfrage v0, dann schickt v0 das Intervall
[last+1,last+i] an die Rückadresse und setzt last:=last+i.
• Erreicht eine dequeue(Q,i) Anfrage v0, dann schickt v0 das Intervall
[first, min{first+i-1,last}] an die Rückadresse und setzt first:=first+i
• Auf dem Rückweg werden die enqueue und dequeue Anfragen wie
die push und pull Anfragen behandelt.
12.07.2012
VADS - Kapitel 6
125
Verteilte Queue
Satz 6.5: Die verteilte Queue benötigt (mit einer verteilten
Hashtabelle auf Basis eines dynamischen de Bruijn
Netzwerks) für die Operationen
• enqueue(Q,x): erwartete Zeit O(log n)
• dequeue(Q): erwartete Zeit O(log n)
Verwaltung mehrer Queues in derselben Hashtabelle:
weise jeder Queue statt Punkt 0 einen (pseudo-)
zufälligen Punkt in [0,1) zu.
12.07.2012
VADS - Kapitel 6
126
Übersicht
•
•
•
•
•
Verteilte Hashtabelle
Verteilte Suchstruktur
Verteilter Stack
Verteilte Queue
Verteilter Heap
12.07.2012
VADS - Kapitel 6
127
Konventioneller Heap
Ein Heap H unterstützt folgende Operationen:
• insert(H,x): fügt Element x in den Heap H ein
(die Priorität wird über key(x) bestimmt).
• deleteMin(H): entfernt das Element x mit kleinstem
key(x) aus H und gibt es zurück
Zwei Invarianten:
• Form-Invariante:vollständiger
Binärbaum bis auf unterste Ebene
• Heap-Invariante:
key(e1)≤min{key(e2),key(e3)}
12.07.2012
VADS - Kapitel 6
e1
e2
e3
128
Verteilter Heap
Viele Subjekte agieren auf Heap:
12.07.2012
VADS - Kapitel 6
129
Verteilter Heap
Probleme:
• Speicherung des Heaps
• Realisierung von insert und deleteMin
12.07.2012
VADS - Kapitel 6
130
Verteilter Heap
Speicherung des Heaps:
• Jedes Element x besitzt eine eindeutige
Position pos(x)≥1 im Heap wie bei der
Feldrealisierung des konventionellen Heaps
e1
e2
e4
e8
e1
12.07.2012
e3
e5
e6
e7
e9
e2
e3
e4
e5
e6
VADS - Kapitel 6
e7
e8
e9
131
Verteilter Heap
Speicherung des Heaps:
• Jedes Element x besitzt eine eindeutige
Position pos(x)≥1 im Heap wie bei der
Feldrealisierung des konventionellen Heaps
• Verwende eine verteilte Hashtabelle, um die
Elemente x gleichmäßig mit Schlüsselwert
pos(x) zu speichern.
• Topologie für Hashtabelle: dynamischer der
Bruijn Graph.
12.07.2012
VADS - Kapitel 6
132
Verteilter Heap
Realisierung von insert(H,x):
1. Stelle insert(H,1)-Anfrage, um eine Nummer pos zu erhalten.
2. Führe insert(pos,x) auf der verteilten Hashtabelle aus, um x
unter pos zu speichern.
Realisierung von deleteMin(H):
1. Stelle deleteMin(H,1)-Anfrage, um eine Nummer pos zu
erhalten.
2. Führe delete(pos) auf der verteilten Hashtabelle aus, um das
unter pos gespeicherte Element x zu löschen und zu
erhalten.
Problem: Punkt 2. in deleteMin nicht gut parallelisierbar!
12.07.2012
VADS - Kapitel 6
133
Verteilter Heap
Idee:
• Verwende Trie Hashing (ohne msd-Knoten), um neue
Elemente einzufügen.
• D.h. die Elemente werden in einem verteilten Suchbaum
gehalten.
• Sollen also über deleteMin k Elemente gelöscht werden, so
sind dies die vordersten k im Suchbaum.
• Die Wurzel des Tries ist zunächst der Anker für alle Anfragen
(die dorthin wie beim verteilten Stack kombiniert werden).
Diese delegiert die Anfragen dann an die Kinder weiter. Jeder
Knoten im Trie merkt sich die Anzahl der Knoten in seinem
Subtrie, damit insert und deleteMin Anfragen massiv parallel
nach unten weitergegeben werden können.
12.07.2012
VADS - Kapitel 6
134
Verteilter Heap
Verteilte Datenstruktur: Patricia Trie
Jeder Knoten u kennt die Anzahl
der Blätter seines Subtries und der
Subtries seiner Kinder (v und w)
und speichert diese in s, s0 und s1,
d.h. s(v)=s0(v)+s1(v).
s0
v
12.07.2012
s
u
s1
w
VADS - Kapitel 6
135
Verteilter Heap
Insert Operation:
• Schicke die Insert(H,i) Operationen durch das de Bruijn Netzwerk
und kombiniere sie auf dem Weg zur Wurzel des Tries. Schicke die
Informationen in der Wurzel (über dessen Kinderlabel) zurück und
setze s(r) auf s(r)+i.
i1
i4
12.07.2012
r i
i2
i3
i=i3+i4
VADS - Kapitel 6
136
Verteilter Heap
Insert Operation:
• Schicke dann die Insert(H,i) Operationen durch das de Bruijn
Netzwerk zu den entsprechenden Kindern der Wurzel und
kombiniere sie auf dem Weg dahin. Schicke die Informationen in
den Kindern zurück und update deren s(v)–Werte auf s(v)+i´ für das
entsprechende i´.
i1
i2
i3
12.07.2012
i4
i5
r
i6
VADS - Kapitel 6
137
Verteilter Heap
Insert Operation:
• Leite so die Insert Operationen durch den Trie, bis sie ihre richtige
Stelle gefunden haben, und integriere sie dort.
• Übung: wie können wir mehrere Elemente an der gleichen Stelle
einfügen?
i1
i2
i3
12.07.2012
i4
i5
r
i6
VADS - Kapitel 6
138
Verteilter Heap
deleteMin Operation:
• Kombiniere zunächst Anfragen deleteMin(H,i) auf dem Weg zur
Wurzel r des Tries und setze s(r) auf max{s(r)-i,0}. Wir nehmen für
die weiteren Erläuterungen an, dass i≤s(r) ist.
i1
i4
12.07.2012
r i
i2
i3
i=i3+i4
VADS - Kapitel 6
139
Verteilter Heap
deleteMin Operation:
• Leite dann Anfrage deleteMin(H,i) durch den Trie und merke für
jeden Knoten u, zu welchen Knoten im Combine-Baum die Anfrage
gehört. Initial ist das die Wurzel r.
i1
i4
r i
i2
i3
u
v
12.07.2012
w
VADS - Kapitel 6
140
Verteilter Heap
deleteMin Operation:
• Ist s0(u)≥i für die Anfrage deleteMin(H,i), leite die Anfrage an das
linke Kind v weiter, behalte die Referenz auf die Combine-BaumKnoten bei, und setze s(v) auf s(v)-i.
i1
i4
r i
i2
i3
u
v
12.07.2012
w
VADS - Kapitel 6
141
Verteilter Heap
deleteMin Operation:
• Ist s0(u)<i für die Anfrage deleteMin(H,i), splitte die Anfrage in zwei
auf: deleteMin(H,s0(u)) für v und deleteMin(H,i-s0(u)) für w.
i1
i2
r´
i4
r i
i3
u
v
12.07.2012
w
VADS - Kapitel 6
142
Verteilter Heap
deleteMin Operation:
• Ist nun für eine dieser Anfragen deleteMin(H,j) j≤i3, dann wird diese
auf Combine-Knoten r´ verwiesen und i3 reduziert auf i3–j. Das
gleiche Verfahren wird auch für i4 angewendet.
i1
i2
r´
i4
r i
i3
u
v
12.07.2012
w
VADS - Kapitel 6
143
Verteilter Heap
deleteMin Operation:
• Wenn die deleteMin Anfragen am Ende die Blätter erreicht haben,
wird jedem Blatt im Combine-Baum genau ein Blatt im Patricia Trie
zugewiesen.
i1
i2
r´
i4
r i
i3
u
v
12.07.2012
w
VADS - Kapitel 6
144
Verteilter Heap
Satz 6.6: Der verteilte Heap benötigt (mit einer verteilten
Hashtabelle auf Basis eines dynamischen de Bruijn
Netzwerks) für die Operationen
• insert(H,x): erwartete Zeit O(log2 n)
• deleteMin(Q): erwartete Zeit O(log n)
Verwaltung mehrer Heaps in derselben Hashtabelle:
weise jeder Queue statt Punkt 0 einen (pseudo-)
zufälligen Punkt in [0,1) zu.
12.07.2012
VADS - Kapitel 6
145
Selbststabilisierung
• Verteiltes Hashing:
Lediglich kontinuierliche Überprüfung, ob Schlüssel
noch dem richtigen Prozess zugeordnet ist. Falls nicht,
dann leite diesen an den richtigen weiter.
• Verteilter Stack, verteilte Queue:
Wie beim verteilten Hashing. Sollte zusätzlich der/die
Zähler in der Wurzel korrumpiert sein, gehen eventuell
Elemente verloren bzw. es wird auf undefinierte
Elemente verwiesen. Um den/die Zähler zu reparieren,
könnte die Wurzel über binäre Suche kontinuierlich
den korrekten Stand des Zählers überprüfen.
12.07.2012
VADS - Kapitel 6
146
Selbststabilisierung
Verteilter Heap:
• Wie beim verteilten Hashing, um die Trie-Knoten im richtigen
Prozess zu speichern. Jeder Trie-Knoten überprüft weiterhin
periodisch, ob die benachbarten Trie-Knoten noch existieren und die
Werte von s(v), s0(v) und s1(v) korrekt sind.
• Vaterknoten existiert nicht: führe die gewöhnliche insert-Operation
für Patricia Tries (die Anfrage läuft den entsprechenden Pfad von
der Wurzel aus hinunter) zur Wiedereinfügung des Knotens durch.
• Kindknoten existiert nicht: Trie kann komprimiert werden, da Knoten
nicht mehr notwendig ist. Führe dazu delete-Operation für den
Knoten durch.
• Für Knoten v ist s(v)≠s0(v)+s1(v): setze s(v) auf s0(v)+s1(v).
• Für den standard Patricia Trie werden keine Blattzuordnungen der
inneren Knoten benötigt. Diese Zuordnungen müssen daher auch
nicht repariert werden.
12.07.2012
VADS - Kapitel 6
147
Fragen?
SS 2012
VADS - Kapitel 6
148
Herunterladen