DHT Distributed Hash Table (Rozproszona Tablica Mieszająca) Janina Mincer-Daszkiewicz Systemy rozproszone MSUI, II rok
Wikipedia Materiały i rysunki zaczerpnięto z następujących źródeł Bogata lista odsyłaczy: http://deim.urv.cat/~cpairot/dhts.html Ion Stoica, Robert Morris, David Karger, M. Frans Kaashoek, Hari Balakrishnan, Chord: A Scalable Peer-topeer Lookup Service for Internet Applications, MIT, SIGCOMM 01, August 2731, 2001 Strona domowa projektu Chord: http://pdos.csail.mit.edu/chord/ G. Urdaneta, G. Pierre, M. van Steen, A Survey of DHT Security Techniques, http://www.globule.org/publi/sdst_acmcs2009.html 2
Inne źródła Maciej Bryński, seminarium SR 2005/06 http://students.mimuw.edu.pl/sr/rok05-06/brynski.pdf Paweł Wiejacha, seminarium SR 2009/10 http://students.mimuw.edu.pl/sr/sr-mono/sr_dht-sec.pdf Designing and Implementing Scalable Applications with Memcached and MySQL, MySQL White Paper http://memcached.org/ 3
Wprowadzenie DHT to klasa zdecentralizowanych systemów rozproszonych zapewniających usługę wyszukiwania (ang. lookup) podobną do tablicy mieszającej DHT przechowuje pary (klucz, wartość), każdy węzeł może efektywnie odszukać wartość związaną z danym kluczem Węzły wspólnie odpowiadają za utrzymywanie odwzorowania kluczy w wartości Główna cecha: skalowalność, mimo częstego dołączania i odłączania węzłów oraz awarii 4
Wprowadzenie - 2 DHT zapewnia infrastrukturę, która pozwala na budowanie bardziej złożonych usług: rozproszone systemy plików, współdzielenie plików na zasadzie P2P, rozproszone zarządzanie treścią, usługi nazewnicze, cooperative web caching, multicast, instant messaging Pierwsza implementacja: w 1998 the Beyond Browsers; w 2001 cztery systemy CAN, Chord, Pastry, Tapestry DHT a DNS czym się różnią? 5
Wprowadzenie - 3 Badania nad DHT prowadzono oryginalnie w celu zastosowania w sieciach P2P takich jak Napster, Gnutella, Freenet Systemy te różnią się sposobem wyszukiwania danych w sieci: Napster: centralny serwer indeksujący, dołączający węzeł wysyła do niego listę lokalnie przechowywanych plików (pojedynczy punkt awarii, problemy prawne) Gnutella: (flooding) każdy komunikat z pytaniem o dane wysyłany do wszystkich węzłów (gorsza wydajność) Freenet: także w pełni rozproszony, z każdym plikiem związany klucz, pliki z podobnymi kluczami gromadzone na podobnym zbiorze węzłów, nie gwarantuje odszukania danych 6
Cechy Decentralizacja Węzły kolektywnie tworzą system, bez centralnej koordynacji Skalowalność System ma działać wydajnie także dla tysięcy i milionów węzłów Odporność na awarie System ma działać stabilnie mimo ciągłego dołączania i odłączania oraz awarii węzłów Niskie koszty administrowania Udaje się to osiągnąć, gdyż każdy węzeł musi się komunikować tylko z kilkoma innymi węzłami w systemie zwykle O(log n), gdzie n to liczba uczestników Musi spełniać także inne wymagania: równoważenie obciążenia, zapewnienie integralności danych, wydajność 7
Sieci P2P Zastosowanie DHT BitTorrent rozproszone trackery, Gnutella, Overnet, KAD emule, MLDonkey Rozproszone systemy plików CFS (Cooperative File System), OceanStore składowanie danych w PlanetLab, Mnemosyne - steganograficzny system plików, PAST Sieci anonimowe Freenet - censorship-resistant distributed data store, GNUnet, Perfect Dark - japoński anonimowy P2P Rozproszone buforowanie w sieci, Systemy CDN CoDeeN - distributed webcache w PlanetLab, Coral Content Distribution Network - webcache/cdn 8
Zastosowanie DHT - 2 Umożliwia rozproszone odszukiwanie dowolnych zasobów: współdzielenie plików: w DHT przechowuje się skrót (hash) pliku i skróty słów kluczowych skojarzonych z plikiem odszukiwanie ludzi (np. w programach typu GG): w DHT przechowuje się skrót nazwiska i skrót klucza publicznego dostarczanie usługi (np. rozproszony backup): w DHT przechowuje się skrót z krótkim opisem usługi Zwykle korzysta się z bezpiecznych funkcji skrótu, takich jak MD5 i SHA1 9
Struktura Podstawą DHT jest przestrzeń kluczy, np. zbiór 160-bitowych napisów (nazw plików) Przestrzeń kluczy jest dzielona pomiędzy węzły sieci Węzły są łączone za pomocą overlay network, która umożliwia znalezienie właściciela dowolnego klucza w przestrzeni kluczy Żeby przechować plik w DHT generuje się skrót nazwy klucz k. Do dowolnego węzła uczestniczącego w DHT wysyła się komunikat put(k, data). Komunikat jest przesyłany po sieci overlay, aż trafi do węzła odpowiedzialnego za klucz k. Ten węzeł zapamiętuje k i dane Dowolny klient może wywołać get(k) w celu odczytania danych. Usunięcie lub dodanie węzła zmienia jedynie zbiór kluczy będących w posiadaniu sąsiadów tego węzła. Overlay network to zbiór adresów przechowywanych w każdym węźle (finger table w Chord), czyli zbiór tablic rutowania 10
Protokoły rutowania Protokoły opisane po raz pierwszy w 2001 Chord (temu przyjrzymy się dokładniej) CAN Content Addressable Network Pastry Tapestry Protokoły opisane po 2001 Kademlia DKS Distributed K-ary System Bamboo 11
Chord Ustalone m (np. 160) liczba bitów identyfikatora. Maksymalnie 2 m węzłów (oznaczmy jako n) chordkey(key) = mbithashfun(key) myid = chordkey(myip) Węzły rozkładamy na okręgu mod 2 m Za klucz K odpowiedzialny jest węzeł o ID >= K mod 2 m Węzły są mniej więcej równomiernie obciążone Podczas dołączania i odłączania węzłów może nastąpić migracja danych (co najwyżej O(1/n)), wymaga O(log 2 n)komunikatów Czasy operacji Wyszukiwanie klucza O(log n) Podłączanie do sieci O(log 2 n) Odłączenie od sieci O(log 2 n) 12
Chord przykładowa sieć N to węzeł sieci, K to klucz 13
Chord struktury danych Każdy węzeł w sieci przechowuje następujące informacje o sieci: następnik kolejny węzeł na okręgu poprzednik poprzedni węzeł na okręgu tablice finger[k] = successor(myid+2 k-1 ), dla k = 1.. log(m) (dla danego k węzeł, który jest w odległości >= 2 k od naszego) Nie wymaga się jak widać, żeby każdy węzeł znał każdy inny (lepsza skalowalność) Całkowity rozmiar struktur danych w węźle to O(log(n)). Istotne jest, żeby te informacje były aktualne 14
Chord przykładowa sieć Tablice finger[k] dla przykładowej sieci 15
Chord przykładowa sieć Wyszukiwanie klucza 54: lookup(54) 16
Chord przykładowe wyszukiwanie Każdy krok wyszukiwania zmniejsza odległość o połowę Oczekiwany czas wyszukiwania O(log (n)) 17
Notacja finger[k].start.interval Chord definicje Definicja (n+2 k-1 ) mod 2 m, 1<= k <= m [finger[k].start, finger[k+1].start).node Pierwszy węzeł >= n.finger[k].start successor predecessor Następny węzeł na liście cyklicznej identyfikatorów; finger[1].node Poprzedni węzeł na liście cyklicznej identyfikatorów 18
Chord przykładowa sieć 2 Przykładowa sieć dla n = 3 zawierająca 3 klucze 19
Chord przykładowa sieć 2 Tablice finger[k] dla przykładowej sieci 20
Chord własności Twierdzenie Dla dowolnego zbioru N węzłów i K kluczy, z dużym prawdopodobieństwem: 1. Każdy węzeł jest odpowiedzialny za co najwyżej (1+eps)K/N kluczy 2. Kiedy (N+1)-szy węzeł dołącza lub odłącza od sieci, odpowiedzialność za O(K/N) węzłów zmienia miejsce (tylko w odniesieniu do węzła dołączającego lub odłączanego) Cechy 1. Każdy węzeł przechowuje informacje tylko o niewielkiej liczbie innych węzłów; wie więcej o węzłach położonych bliżej i mniej o węzłach położonych dalej 2. Tablica rutowania węzła nie zawiera dość informacji, by określić następnika dowolnego węzła K. Na przykład węzeł 3 w podanym przykładzie nie zna następnika węzła 1 (nie ma 1 w tablicy rutowania węzła 3). 3. Taki węzeł szuka węzła o identyfikatorze bliższym K niż własny 21
Chord wyszukiwanie klucza Wyszukiwanie klucza odpowiada znalezieniu następnika dla id // poproś węzeł n o znalezienie następnika dla id n.findsuccessor(id) n = FindPredecessor(id) return n.successor; // poproś węzeł n o znalezienie poprzednika dla id n.findpredecessor(id) n1 = n; while (id in (n1, n1.successor)) n1 = n1.closestprecedingfinger(id); return n1; // przekaż najbliższy finger poprzedzający id n.closestprecedingfinger(id) for i = m downto 1 if (finger[i].node i (n, id)) return n; return finger[i].node; 22
Chord wyszukiwanie przykład Załóżmy, że węzeł 3 chce znaleźć następnika dla identyfikatora 1 Ponieważ 1 należy do cyklicznego przedziału [7,3), więc należy do 3.finger[3].interval. Pobieramy wartość z trzeciej pozycji w tabeli finger, czyli 0 Ponieważ 0 poprzedza 1, więc węzeł 3 prosi węzeł 0 o znalezienie następnika dla 1. Węzeł 0 znajdzie w swojej tabeli, że następnikiem dla 1 jest 1 i przekaże 1 do 3 23
Chord dynamiczne zmiany sieci Żeby zapewnić możliwość znalezienia każdego węzła w sieci, Chord musi zachowywać dwa niezmienniki: Zachowuje się poprawnie informacje o następnikach Dla każdego klucza k, za k jest o odpowiedzialny węzeł successor(k) Dla uproszczenia ograniczamy się do sytuacji gdy dołącza do sieci jeden węzeł 24
Chord dołączenie węzła do sieci Do sieci dołącza węzeł n. Trzeba wykonać następujące czynności: Inicjuj predecessor i finger dla n Popraw predecessor i finger istniejących węzłów, żeby uwzględniały dołączenie n Zawiadom wyższą warstwę oprogramowania, żeby przekazała stan (tzn. wartości) związane z kluczami, za które jest teraz odpowiedzialny węzeł n (w praktyce wystarczy pobrać je z następnika n) Zakładamy, że nowy węzeł sam ustali adres jakiegoś istniejącego węzła n1 25
Chord dołączenie węzła do sieci Inicjuj predecessor i finger dla n n prosi następnika o kopię pełnej tabeli finger i o predecessor. Na bazie tego buduje własne tablice Podejście naiwne: n wykonuje find_successor dla każdej z m pozycji w tablicy finger (koszt: O(m log n)) Efektywniej: n sprawdza, czy finger dla i jest poprawnym finger dla (i+1). Ta jest, gdy finger[i].interval jest pusty, a więc finger[i].node >= finger[i+1].start (koszt: O(log n) Popraw finger dla istniejących węzłów Węzeł n stanie się i-tym finger węzła p, gdy p poprzedza n o co najmniej 2 i-1, i-ty finger węzła p następuje po n. 26
Chord dołączenie węzła do sieci Tablice finger[k] po dołączeniu nowego węzła (czarne zmienione, szare bez zmian) 27
Chord odłączenie węzła z sieci Tablice finger[k] po odłączeniu istniejącego węzła 28
Zalety dobra wydajność Wady Chord podsumowanie skomplikowana implementacja duża wrażliwość na awarie węzłów brak równoległości przy wyszukiwaniu 29
Memcached Rozproszony system buforowania ogólnego przeznaczenia. Często używany w celu przyspieszenia aplikacji webowych pobierających duże ilości danych z bazy. Dane i obiekty są buforowane w pamięci RAM API Memcached dostarcza olbrzymią tablicę mieszającą rozproszoną pomiędzy wiele maszyn. Pierwotnie użyta przez Danga Interactive na potrzeby serwisu społecznościowego LiveJournal Używany w wielu dużych, znanych serwisach webowych, np. YouTube, LiveYournal, Wikipedia/Wikimedia, Amazon.com, Wiki, SourceForge, Metacafe, Facebook, Twitter, Fotolog, The Pirate Bay, Netlog Dostępny jako projekt open source na licencji BSD Facebook ma największą farmę 800 serwerów Memcached 30
Memcached Architektura klient-serwer. Serwery utrzymują słownik, klienci wypełniają słownik i go przepytują. Klucze mają do 250 bajtów, wartości mogą mieć do 1 MB. Klient korzysta z biblioteki, zna wszystkie serwery. Serwery nie komunikują się ze sobą. Biblioteka klienta liczy skrót klucza w celu określenia serwera, kontaktuje się bezpośrednio z tym serwerem. Serwer wylicza drugi skrót klucza, dla określenia miejsca, w którym umieści wartość. Serwery trzymają wartości w RAM, gdy pamięci zaczyna brakować, to usuwają najstarsze wartości (w porządku LRU) Wybór klucza: należy do programisty. Przykład: key ::= data type name : primary key Można skompilować Memcached z SASL (gdy wymagane jest bezpieczeństwo) 31
Serwer Memcached Implementuje własny alokator płytowy ( jak Linux) Klucze ograniczone do 250 znaków, buforowane dane nie mogą przekroczyć największego rozmiaru płyty (obecnie 1 MB) Często wykorzystuje się Memcached do buforowania wyników zapytań do bazy danych Klient dostępny dla wielu języków programowania 32
33
Memcached API function get_foo(int userid) { /* first try the cache */ data = memcached_fetch("userrow:" + userid); if (!data) { /* not found : request database */ data = db_select("select * FROM users WHERE userid =?", userid); /* then store in cache until next get */ memcached_add("userrow:" + userid, data); } return data; } 34
Memcached API function update_foo(int userid, string dbupdatestring) { /* first update database */ result = db_execute(dbupdatestring); if (result) { /* database update successful : fetch data to be stored in cache */ data = db_select("select * FROM users WHERE userid =?", userid); /* last line could also look like data = createdatafromdbstring(dbupdatestring); */ /* then store in cache until next get */ memcached_set("userrow:" + userid, data); } } (alternatywne rozwiązanie: usunąć zmienioną wartość ze schowka) 35
Serwer Memcached Architektura: Jeden serwer MySQL i kilka serwerów Memcached pozwala skalować aplikacje zorientowane na odczyt Jeden master serwer MySQL, kilka slave serwerów MySQL, kilka serwerów Memcached pozwala skalować aplikacje zorientowane na odczyt Sharding (podział aplikacji) podział danych na wiele fizycznych serwerów, w celu dobrej skalowalności odczytów i zapisów 36
37
38
39