Apache Hadoop - framework do pisania aplikacji rozproszonych

Transkrypt

Apache Hadoop - framework do pisania aplikacji rozproszonych
Apache Hadoop - framework do pisania aplikacji
rozproszonych
Piotr Praczyk
5 lipca 2009
1
Wprowadzenie
Istnieje wiele rodzajów obliczeń, których wykonywanie na pojedynczej maszynie,
nawet najpotężniejszej, jest zbyt czasochłonne. Wśród takich zadań wymienić
można analizowanie skomplikowanych danych (na przykład Seti@Home, dane
z LHC etc...), albo przetwarzanie ogromnych ich ilości (na przykład Google
Maps). Z tego powodu rozwijane są narzędzia ułatwiające wykonywanie obliczeń
na wielu komputerach jednocześnie.
W przypadku tradycyjnych podejść, programista musi samemu rozwiązywać
problemy narastające między innymi kiedy więcej niż jeden działający fragment
obliczenia chce uzyskać dostęp do zasobu, kiedy potrzebna jest komunikacja
między maszynami itp.
Google zaproponował własny paradygmat tworzenia aplikacji rozproszonych,
Map Reduce [3] Struktura programów napisanych zgodnie z nim, ułatwia rozwiązywanie wielu skomplikowanych problemów współbieżności automatycznie,
ułatwiając zadanie programisty. Przedstawione podejście sprawdza się wyjątkowo dobrze w przypadku programowania zadań wymagających przetwarzania
dużych ilości danych.
Apache Hadoop jest wolną implementacją Map Reduce. Jest wykorzystywany przez wiele dużych firm takich, jak Yahoo, Amazon czy Facebook. Google
posiada własną implementację Map Reduce, którą wykorzystuje wewnętrznie.
Hadoop składa się z oprogramowania uruchamianego na maszynach przeznaczonych do wykonywania obliczeń i przechowywania danych oraz z zestawu
bibliotek umożliwiających pisanie zadań. Językiem, w którym Hadoop jest napisany, jest głównie Java. Konsekwencją tego jest dostarczenie największej liczby
interfejsów programistycznych dla tego języka. Również najbardziej naturalną
metodą tworzenia programów działających pod kontrolą Hadoop, jest dostarczenie odpowiednich klas w Javie. Istnieje możliwość wykorzystania dowolnego
innego języka programowania. Czasami możliwe jest również uruchomienie istniejącego programu, jako części zadania Map Reduce, bez ingerencji w jego
strukturę wewnętrzną.
1
2
Podstawy Map Reduce
W najprostszym przypadku, przygotowanie zadania dla Map Reduce, sprowadza się do zaimplementowania dwóch funkcji, map oraz reduce. Konieczne jest
również zdefiniowanie położenia danych wejściowych oraz miejsca, gdzie mają
być składowane wyniki. Zadaniem funkcji map jest wykonanie pewnych obliczeń
na przekazanym jej fragmencie danych wejściowych oraz wygenerowanie ciągu
par składających się z klucza oraz przypisanej mu wartości.
Dane wygenerowane w tym kroku, są agregowane z wykorzystaniem klucza
oraz przekazywane do funkcji reduce. Każde wywołanie reduce związane jest z
jednym kluczem oraz listą wszystkich odpowiadających mu wartości. Zadanie
funkcji reduce polega na wygenerowaniu par stanowiących wynik obliczenia. Są
one zapisywane w lokalizacji wskazanej jako wyjściowa. Rysunek 1 pokazuje
strukturę dowolnego obliczenia Map Reduce.
Rysunek 1: Elementy zadania Map Reduce
Dopóki cały opisany proces odbywa się na jednej maszynie, stosowanie infrastruktury związanej z Map Reduce wiąże się głównie ze stratami wydajności.
Jeśli jednak dane wejściowe są odpowiednio duże, implementacja Map Reduce
(na przykład Hadoop) zadba o to, aby obliczenia zostały automatycznie rozproszone. Rysunek 2 przedstawia schemat wykonania zadania przygotowanego
dla Hadoop na wielu maszynach jednocześnie. Na pierwszy rzut oka, rozwiązanie wydaje się dość niewydajne, ponieważ przesyłanie dużych ilości danych za
pośrednictwem sieci jest stosunkowo wolnym procesem. Hadoop stara się umieszczać obliczenia na tych samych maszynach, gdzie przechowywane są dane. Jeśli
nie jest to możliwe, obliczenia wykonywane są w miejscach, które są bliskie ze
względu na szybkość połączenia sieciowego.
Klasycznym przykładem zastosowania paradygmatu Map Reduce, opisanym
w [3], jest generowanie statystyk słów pojawiających się w tekście przekazanym
jako wejście. Funkcja map, odpowiedzialna może być w takim przypadku za podzielenie otrzymanego napisu na wyrazy oraz wygenerowanie par zawierających
wyraz jako klucz oraz liczbę 1 jako wartość. W następnym kroku, framework
automatycznie pogrupuje pary ze względu na słowa będące kluczami par. Zadaniem funkcji reduce będzie policzenie, ile par zostało przekazanych dla danego
słowa, oraz zwrócenie pary składającej się z rozważanego słowa oraz liczby jego
wystąpień.
Rysunek 3 pokazuje, jak może przebiegać liczenie słów w przykładowym
tekście.
2
Rysunek 2: Struktura rozproszonego Map Reduce
Rysunek 3: Liczenie statystyk słów w tekście z wykorzystaniem Map Reduce
3
2.1
Implementacje zadań
Domyślnym sposobem implementacji zadań dla Hadoop, jest przygotowanie klas
Javy, implementujących interfejsy Mapper oraz Reducer odpowiedzialne odpowiednio za etapy map oraz reduce tworzonego zadania. Oba interfejsy wymagają, aby zostały określone typy par pojawiających się na wejściu oraz wyjściu odpowiednich kroków, z tego powodu są zaimplementowane jako interfejsy
generyczne pobierające 4 typy jako argumenty. Składnia dla tych interfejsów
przedstawiona jest na listingu 4
Mapper<InputKeyType , InputValType , IntermKeyType , IntermValType>
Reducer<IntermKeyType , IntermValType , OutputKeyType , OutputValType>
Rysunek 4: Składnia interfejsów wykorzystywanych przy implementacji zadań
Map Reduce w Javie
2.2
Odporność na awarie
Hadoop został zaprojektowany, aby możliwe było wykonywanie z jego pomocą
obliczeń na zwyczajnych komputerach. Wiąże się to z o wiele większą podatnością na awarie i błędy. Jeden z węzłów wykorzystywanego klastra jest odpowiedzialny za śledzenie obliczeń. Jeśli wykryta zostanie awaria, część zadania jest
powtarzana na innej maszynie.
3
W jaki sposób wspierane są heurystyki dbające o lokalność obliczeń?
Aby możliwe było wykonywanie obliczeń w pobliżu danych przeznaczonych do
przetworzenia, konieczne jest posiadanie informacji na temat ich lokacji. Stosowanie zwykłego systemu plików, dostarczanego przez system operacyjny nie jest
dobrym rozwiązaniem ze względu na wysoki poziom abstrakcji danych. W przypadku systemów unixowych, system stara się ukryć szczegóły dotyczące fizycznego przechowywania danych poprzez utrzymywanie wirtualnego drzewa katalogów. Dzięki temu możliwe jest działanie tych samych programów na różnych
zbiorach danych, często przechowywanych w sposób nie rozważany w trakcie
pisania aplikacji. Jednocześnie jednak program taka nie jest w stanie odróżnić,
czy plik znajduje się na lokalnej maszynie, czy może jest jedynie widoczny za
pośrednictwem sieciowego systemu plików a zatem nie jest w stanie określić, jak
kosztowne będzie jego odczytanie. Z tego powodu konieczne jest zastosowanie
innych rozwiązań.
4
3.1
HDFS
Domyślną metodą przechowywania danych przez Hadoop jest dedykowany rozproszony system plików, HDFS (Hadoop Distributed File System). Został on
zaprojektowany, aby zoptymalizować wykonywanie czynności związanych z Map
Reduce, takich jak szybki dostęp do dużych, spójnych obszarów danych, udostępnianie informacji o fizycznym ich położeniu, tworzenie kopii danych na innych maszynach zgodnie z topologią sieci.
Aby przyspieszyć powyższe operacje, niektóre standardowe wymagania stawiane przed systemem plików, wymienione w specyfikacji POSIX, nie zostały
spełnione.
W HDFS wspierany jest model, według którego pliki zapisywane są tylko
raz, lecz mogą być odczytywane wielokrotnie. Możliwe jest również dopisywanie
danych na końcu istniejących już plików, jednak w obecnej wersji funkcjonalność
ta nie jest jeszcze uważana za stabilną.
Aby zapewnić całkowitą lokalność danych, te same maszyny powinny być
wykorzystywane do obliczeń jak i przechowywania danych.
Ze względu na to, że zadania Map Reduce, z natury przetwarzają duże ilości
danych, system plików HDFS posiada duży rozmiar bloku. Dzięki temu, obciążenie związane z przechowywaniem i uzyskiwaniem metadanych jest o wiele
mniejsze niż w przypadku standardowych rozwiązań. konsekwencją takiego podejścia jest jednak to, że HDFS nie nadaje się do przechowywania wielu małych
plików [4]. Za każdym razem kiedy plik jest zapisywany, najmniejsza liczba bloków dostarczająca potrzebnej przestrzeni dyskowej, jest alokowana. Jeśli plik
nie wykorzystuje pełnego bloku, reszta pozostaje pusta.
Uruchamiając zadanie Hadoop, jako parametr można przekazać foldery służące do przechowywania tych danych. Wszystkie operacje na plikach zostaną
wykonane automatycznie a program otrzyma na wejściu odpowiednie pary.
Istnieje sterownik wykorzystujący bibliotekę Fuse, który pozwala na zmontowanie HDFS w drzewie katalogów. Domyślnym sposobem dostępu do systemu
plików jest jednak wywołanie Hadoop z parametrem dfs. Udostępniane operacje
są podobne do tych udostępnianych przez powłokę systemową w stosunku do
zwykłych systemów plików.
3.2
HBase
Czasami system plików nie jest najlepszym rozwiązaniem. Może tak się zdarzyć,
kiedy na przykład specyfika rozwiązywanego problemu wymaga przechowywania
wielu niewielkich porcji danych.
HBase jest implementacją rozproszonej bazy danych BigTable, przedstawionej przez Google w [2].
HBase nie jest relacyjną bazą danych, lecz tak zwanym Key-value store. Dane przechowywane są w strukturze przypominającej wielopoziomowy słownik.
Kluczami są dowolne ciągi bajtów. Dane są fizycznie przechowywane w kolejności leksykograficznej względem klucza, co pozwala na szybkie wyszukiwanie
oraz na pewne optymalizacje przy tworzeniu zadań.
5
Podobnie, jak w przypadku HDFS, HBase została zoptymalizowana pod kątem operacji typowych dla Map Reduce. Zrezygnowano z funkcjonalności, które
były kosztowne w przypadku rozproszonych, relacyjnych baz danych. Z tego
powodu nie ma możliwości definiowania logicznych powiązań między danymi,
takich jak klucze obce.
Również obsługa transakcji jest bardzo okrojona i ogranicza się do atomowego wykonywania ciągu operacji dotyczących jednego wiersza.
W chwili pisania tego teksu, jedynie API dla języka Java było dostępne.
3.3
Możliwość implementacji własnych formatów wejściowych
Lista możliwych źródeł danych wejściowych oraz sposobów zapisywania wyników nie ogranicza się do opisanych powyżej. Możliwe jest wykorzystanie tradycyjnych systemów plików oraz relacyjnych baz danych, w przypadku których
korzyści związane z lokalnością obliczeń zostaną utracone.
Istnieje również możliwość implementacji własnych źródeł danych. Zadanie
takie sprowadza się do napisania zestawu klas w Javie, implementujących interfejsy InputFormat, RecordReader oraz InputSplit. Dzięki temu możliwa jest
współpraca zadań Hadoop z dowolnymi nośnikami, możliwe jest konwertowanie
danych w locie a nawet generowanie ich w czasie wykonania.
Sytuacja wygląda podobnie w przypadku sposobów przechowywania wyników.
4
Alternatywne metody implementacji zadań Map
Reduce
Często implementacja zadań w języku Java nie jest najwygodniejszym rozwiązaniem. Powodem mogą być sytuacje kiedy zamknięta biblioteka programistyczna,
niedostępna w Javie, musi zostać wykorzystana. Czasami wygodne mogło by być
również wykorzystywanie gotowych programów, jako zadań Map Reduce.
Hadoop udostępnia dwa interfejsy pozwalające na wykorzystanie innych języków programowania. Stosowanie ich wiąże się z pewnymi ograniczeniami w
stosunku do stosowania natywnej implementacji. W niektórych sytuacjach może być jednak wygodne.
4.1
Streaming
Najbardziej uniwersalnym interfejsem programistycznym jest Hadoop Streaming.
Pozwala on na wykorzystanie dowolnego programu w obu krokach wykonywania zadania Map Reduce. Dane wejściowe przekazywane są za pomocą standardowego wejścia. Dane wyjściowe powinny zostać przekazane przez standardowe
wyjście. Ponieważ dane składają się z ciągu par klucz, wartość, zdefiniowany jest
sposób interpretacji napisów. Każda linia koduje jedną parę. Istnieje możliwość
zdefiniowania separatora. W obecnej wersji Hadoop nie wspiera przekazywania
6
danych binarnych przy stosowaniu Streamingu, są jednak plany zaimplementowania tej funkcjonalności w przyszłości.
Dzięki opisanemu sposobowi komunikacji z frameworkiem, możliwe jest wykorzystanie istniejących programów jako zadań Hadoop. Możliwe jest również
uruchamianie ciągów poleceń powłoki.
4.2
Pipes
Kolejny z dostarczonych interfejsów programistycznych jest dedykowany dla języka C++. Zamiast implementacji klas w Javie, umożliwia on dostarczenie klas
C++. Muszą one dziedziczyć po klasach zdefiniowanych w odpowiednim pliku
nagłówkowym będącym częścią dystrybucji Hadoop.
Rozwiązanie te jest mniej uniwersalne, jednak pozwala na większą kontrolę nad zadaniem. Dzięki zastosowaniu struktur danych języka programowania,
łatwy jest dostęp do wewnętrznych struktur opisujących zadanie. Są one mapowane na odpowiednie obiekty C++.
Podobnie, jak w przypadku stosowania Streamingu, pojawiają się problemy
przy przekazywaniu danych binarnych.
Przy zastosowaniu SWIG, możliwe jest stworzenie wrapperów dla wielu języków programowania.
Stosowanie zarówno Hadoop Pipes jak i Streamingu, może łączyć się z wykorzystaniem dowolnych formatów wejściowych, wyjściowych oraz innych wtyczek
dla Hadoop. Elementy te muszą być jednak zaimplementowane w Javie.
5
Projekty związane z Map Reduce
Poza HBase, istnieją również inne projekty związane z Hadoop, rozszerzające
jego możliwości albo pozwalające na wykonywanie konkretnych rodzajów obliczeń. Kilka przykładów zostało opisanych poniżej.
5.1
Dumbo
Dumbo jest biblioteką języka Python, oraz zestawem narzędzi usprawniających
pisanie zadań korzystających z Hadoop Streaming. Wśród dostarczanych udogodnień, warto wymienić automateczne parsowanie wejścia i przekazywanie go
do funkcji map i reduce za pomocą odpowiednich struktur danych oraz wsparcie
dla przekazywania danych binarnych.
5.2
Hama
Hama jest biblioteką pozwalającą na wykonywanie operacji na dużych macierzach z wykorzystaniem Map Reduce a w szczególności Hadoop. W obecnym
stadium rozwoju brakuje jej wiele funkcji, jak liczenia wartości własnych, w
związku z czym jest rozwijana w ramach Apache Incubator.
7
5.3
Mahout
Projekt Mahout ma na celu dostarczenie bibliotek wspomagających uczenie maszynowe, wykorzystujących Hadoop w celu wykonywania obliczeń.
5.4
Hadoop a Cloud Computing
Najbardziej oczywistą metodą uzyskania dostępu do klastra działającego pod
kontrolą Hadoop jest własnoręczne skonfigurowanie takiego. Nie jest to jednak
jedyna możliwość. Firma Amazon, udostępnia instalację Hadoop w ramach swoich serwisów Cloud Computing [1]. Korzystając ze strony internetowej, możliwe
jest uruchomienie dowolnej liczby maszyn mających wykonywać zadania Map
Reduce. Opłaty pobierane są od godziny działania instalacji. Dzięki takiemu
podejściu, możliwe jest dynamiczne rezerwowanie oraz zwalnianie potrzebnych
zasobów co może prowadzić do zmniejszenia kosztów działania instalacji.
Niekorzystnym efektem pojawiającym się przy stosowaniu rozwiązania Amazon jest to, że dane trzymane są domyślnie w sieciowym systemie plików S3. W
efekcie, rozwiązanie nie korzysta z lokalności obliczeń. Czasami jednak, na przykład kiedy ilość obliczeń jest duża w porównaniu z ilością danych, nie ma to
dużego znaczenia.
5.5
Couldera
Firma Cloudera dostarcza komercyjną dystrybucję Hadoop zawierającą dodatkowe narzędzia konfiguracyjne. Oferuje również wsparcie techniczne.
6
Podsumowanie
Map Reduce wydaje się być dobrą alternatywą dla standardowych API umożliwiających pisanie aplikacji rozproszonych. Wiele problemów daje się wyrazić za
pomocą tego paradygmatu w bardzo naturalny sposób, czyniąc powstałe programy bardziej czytelnymi.
Pomimo stosunkowo wczesnej fazy rozwoju, projekt Hadoop udowodnił już
swoją przydatność. Wiele znanych firm wykorzystuje go do przetwarzania danych na wielką skalę.
Dzięki przejrzystej strukturze Map Reduce, łatwo jest zacząć pisać własne
zadania działające pod kontrolą Hadoop. Implementacja pozwalająca pisać własne wtyczki, jak na przykład formaty wejścia i wyjścia, zwiększa rozdział komponentów programu sprawiając, że podatność na błędy jest o wiele mniejsza.
Literatura
[1] Amazon elastic mapreduce.
[2] F. Chang, J. Dean, S. Ghemawat, W. C. Hsieh, D. A. Wallach, M. Burrows,
T. Chandra, A. Fikes, and R. E. Gruber. Bigtable: a distributed storage
8
system for structured data. In OSDI ’06: Proceedings of the 7th symposium
on Operating systems design and implementation, pages 205–218, Berkeley,
CA, USA, 2006. USENIX Association.
[3] J. Dean and S. Ghemawat. Mapreduce: simplified data processing on large
clusters. Commun. ACM, 51(1):107–113, 2008.
[4] T. White. The Small Files Problem.
9

Podobne dokumenty