Samouczek HDFS: Architecture, Czytaj i pisz Operacja

⚡ Inteligentne podsumowanie

HDFS to rozproszona warstwa pamięci masowej Hadoop, dzieląca bardzo duże pliki na powielone bloki na maszynach komercyjnych, tak aby pojedynczy NameNode tracmetadanych ks, podczas gdy wiele węzłów danych niezawodnie obsługuje żądania odczytu i zapisu.

  • 🔘 Archistruktura: NameNode przechowuje obraz przestrzeni nazw i dziennik edycji, podczas gdy DataNode przechowuje rzeczywiste repliki bloków.
  • ️ Rozmiar bloku: Domyślna wielkość bloków w Hadoop 1.x wynosiła 64 MB; w Hadoop 2.x i 3.x jest to 128 MB.
  • ✅ Replikacja: Domyślnie na blok przypadają trzy repliki, rozmieszczone na różnych stojakach, dzięki czemu awaria sprzętu nigdy nie spowoduje utraty danych.
  • 🧪 Odczyt ścieżki: FSDataInputStream i DFSInputStream pobierają lokalizację bloków z NameNode, a następnie przesyłają strumieniowo bajty bezpośrednio z DataNode.
  • 🛠️. Ścieżka zapisu: DFSOutputStream kolejkuje pakiety, DataStreamer buduje potok DataNode, a kolejka Ack chroni przed utratą pakietów.
  • 🧭 Opcje dostępu: org.apache.hadoop.fs Java API i powłoka hdfs dfs umożliwiają otwieranie, odczytywanie, zapisywanie i zamykanie.

Samouczek HDFS

Co to jest HDFS?

HDFS to rozproszony system plików do przechowywania bardzo dużych plików danych, działający na klastrach sprzętu powszechnego użytku. Jest odporny na błędy, skalowalny i niezwykle prosty w rozbudowie. Hadoop jest dostarczany z HDFS (Hadoop Distributed File System).

Gdy dane przekraczają pojemność pamięci masowej na pojedynczej maszynie fizycznej, konieczne staje się podzielenie ich na kilka oddzielnych maszyn. System plików, który zarządza operacjami specyficznymi dla pamięci masowej w sieci maszyn, nazywa się rozproszonym systemem plików. HDFS jest jednym z takich oprogramowań.

HDFS Architektura

Klaster HDFS składa się głównie z NazwaNode który zarządza metadanymi systemu plików i Węzły danych które przechowują rzeczywiste dane.

  • NazwaWęzeł: Węzeł NameNode można uznać za głównego administratora systemu. Utrzymuje on drzewo systemu plików oraz metadane wszystkich plików i katalogów obecnych w systemie. Dwa pliki: „obraz przestrzeni nazw” i „dziennik edycji” służą do przechowywania metadanych. Węzeł NameNode posiada wiedzę o wszystkich węzłach danych zawierających bloki danych dla danego pliku, jednak nie przechowuje trwale lokalizacji bloków. Informacje te są rekonstruowane z węzłów danych za każdym razem, gdy system się uruchamia.
  • Węzeł danych: Węzły danych to węzły podrzędne, które znajdują się na każdej maszynie w klastrze i zapewniają rzeczywistą pamięć masową. Odpowiadają za obsługę żądań odczytu i zapisu od klientów.

Ponieważ pojedynczy NameNode mógłby stać się pojedynczym punktem awarii, obecne klastry uruchamiają aktywny NameNode obok zapasowego NameNode, który udostępnia dziennik edycji za pośrednictwem kworum JournalNode, z automatycznym przełączaniem awaryjnym między nimi.

Operacje odczytu i zapisu w systemie HDFS działają na poziomie bloków. Pliki danych w systemie HDFS są dzielone na fragmenty o rozmiarze bloku, które są przechowywane jako niezależne jednostki. Domyślny rozmiar bloku w systemie Hadoop 1.x wynosi 64 MB. Od wersji Hadoop 2.x domyślny rozmiar bloku wynosi 64 MB. dfs.rozmiar bloku wynosi 128 MB.

HDFS opiera się na koncepcji replikacji danych, w której tworzone są liczne repliki bloków danych, które są następnie rozmieszczane na węzłach w klastrze, aby zapewnić wysoką dostępność danych w przypadku awarii węzła. Domyślny współczynnik replikacji wynosi trzy (replikacja dfs), a gdy DataNode przestaje wysyłać sygnały potwierdzające, NameNode automatycznie replikuje swoje bloki w innym miejscu.

Czy wiesz? Plik w HDFS, który jest mniejszy niż pojedynczy blok, nie zajmuje całej pamięci bloku.

Czytaj Operaw HDFS

Żądanie odczytu danych jest obsługiwane przez HDFS, NameNode i DataNode. Czytnik nazwijmy „klientem”. Poniższy diagram przedstawia operację odczytu pliku w Hadoop.

Przepływ danych operacji odczytu HDFS pomiędzy klientem, NameNode i DataNodes

  1. Klient inicjuje żądanie odczytu, wywołując metodę „open()” obiektu FileSystem; jest to obiekt typu DistributedFileSystem.
  2. Ten obiekt łączy się z węzłem NameNode za pomocą RPC i pobiera metadane, takie jak lokalizacje bloków pliku. Należy pamiętać, że adresy te dotyczą pierwszych kilku bloków pliku.
  3. W odpowiedzi na to żądanie metadanych zwracane są adresy węzłów danych posiadających kopię danego bloku.
  4. Po otrzymaniu adresów węzłów danych, klientowi zwracany jest obiekt typu FSDataInputStream. Strumień FSDataInputStream zawiera strumień DFSInputStream, który obsługuje interakcje z węzłem danych i węzłem nazw. W kroku 4, pokazanym na powyższym diagramie, klient wywołuje metodę „read()”, która powoduje, że strumień DFSInputStream nawiązuje połączenie z pierwszym węzłem danych przechowującym pierwszy blok pliku.
  5. Dane są odczytywane w postaci strumieni, w których klient wielokrotnie wywołuje metodę „read()”. Proces operacji read() jest kontynuowany aż do końca bloku.
  6. Po osiągnięciu końca bloku DFSInputStream zamyka połączenie i przechodzi do lokalizowania następnego węzła danych dla następnego bloku.
  7. Po zakończeniu odczytu klient wywołuje metodę close().

Pisać Operaw HDFS

W tej sekcji dowiesz się, jak dane są zapisywane w systemie HDFS za pośrednictwem plików. Poniższy diagram traces, które zapisują ścieżkę.

Potok operacji zapisu HDFS z DataQueue, DataStreamer i Ack Queue

  1. Klient inicjuje operację zapisu, wywołując metodę „create()” obiektu DistributedFileSystem, która tworzy nowy plik – krok nr 1 na powyższym diagramie.
  2. Obiekt DistributedFileSystem łączy się z węzłem NameNode za pomocą wywołania RPC i inicjuje tworzenie nowego pliku. Operacja ta nie wiąże jednak żadnych bloków z plikiem. Obowiązkiem węzła NameNode jest sprawdzenie, czy plik (który jest tworzony) już nie istnieje i czy klient ma odpowiednie uprawnienia do utworzenia nowego pliku. Jeśli plik już istnieje lub klient nie ma wystarczających uprawnień do utworzenia nowego pliku, zgłaszany jest wyjątek IOException. W przeciwnym razie operacja kończy się powodzeniem, a węzeł NameNode tworzy nowy rekord dla pliku.
  3. Po utworzeniu nowego rekordu w NameNode, klientowi zwracany jest obiekt typu FSDataOutputStream. Klient używa go do zapisu danych w systemie HDFS. Wywoływana jest metoda zapisu danych (krok 3 na diagramie).
  4. Strumień FSDataOutputStream zawiera obiekt DFSOutputStream, który zarządza komunikacją z węzłami DataNode i węzłem NameNode. Podczas gdy klient kontynuuje zapisywanie danych, DFSOutputStream kontynuuje tworzenie pakietów z tymi danymi. Pakiety te są umieszczane w kolejce zwanej kolejką danych (DataQueue).
  5. Istnieje jeszcze jeden komponent o nazwie DataStreamer, który pobiera tę kolejkę danych. DataStreamer prosi również NameNode o przydzielenie nowych bloków, wybierając w ten sposób pożądane DataNode do użycia w replikacji.
  6. Teraz proces replikacji rozpoczyna się od utworzenia potoku przy użyciu DataNodes. W naszym przypadku wybraliśmy poziom replikacji 3, dlatego w potoku znajdują się 3 DataNodes.
  7. DataStreamer przesyła pakiety do pierwszego węzła DataNode w potoku.
  8. Każdy węzeł danych w potoku przechowuje odebrany pakiet i przesyła go dalej do drugiego węzła danych w potoku.
  9. Inna kolejka, „Ack Queue”, jest obsługiwana przez DFSOutputStream i służy do przechowywania pakietów oczekujących na potwierdzenie od DataNodes.
  10. Po otrzymaniu potwierdzenia dla pakietu w kolejce od wszystkich DataNode w potoku, jest on usuwany z „Ack Queue”. W przypadku awarii dowolnego DataNode, pakiety z tej kolejki są używane do ponownego zainicjowania operacji.
  11. Po zakończeniu zapisywania danych przez klienta, wywołuje on metodę close() (krok 9 na diagramie). Wywołanie close() powoduje przekazanie pozostałych pakietów danych do potoku, a następnie oczekiwanie na potwierdzenie.
  12. Po otrzymaniu ostatecznego potwierdzenia nawiązywany jest kontakt z NameNode w celu poinformowania go, że operacja zapisu pliku została zakończona.

Uzyskaj dostęp do HDFS za pomocą Java API

W tej sekcji staramy się zrozumieć Java interfejs używany do uzyskiwania dostępu do systemu plików Hadoopa.

Aby programowo współdziałać z systemem plików Hadoop, Hadoop zapewnia wiele Java Klasy. Pakiet o nazwie org.apache.hadoop.fs zawiera klasy przydatne do manipulowania plikiem w systemie plików Hadoop. Operacje te obejmują otwieranie, odczytywanie, zapisywanie i zamykanie. Interfejs API plików Hadoop jest uniwersalny i można go rozszerzyć o interakcję z systemami plików innymi niż HDFS.

Odczyt pliku z HDFS, programowo

Obiekt java.net.URL służy do odczytywania zawartości pliku. Na początek musimy zrobić Java rozpoznaj hdfs Hadoop URL schemat. Odbywa się to poprzez wywołanie zestawuURLMetoda StreamHandlerFactory na URL obiekt i przekazując do niego instancję FsUrlStreamHandlerFactory. Tę metodę należy wykonać tylko raz na FMV, stąd jest zamknięty w bloku statycznym.

Przykładowy kod to-

public class URLCat {
    static {
        URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory());
    }
    public static void main(String[] args) throws Exception {
        InputStream in = null;
        try {
            in = new URL(args[0]).openStream();
            IOUtils.copyBytes(in, System.out, 4096, false);
        } finally {
            IOUtils.closeStream(in);
        }
    }
}

Ten kod otwiera i odczytuje zawartość pliku. Ścieżka do tego pliku w systemie HDFS jest przekazywana do programu jako argument wiersza poleceń.

Dostęp do HDFS za pomocą interfejsu wiersza poleceń

To jeden z najprostszych sposobów interakcji z systemem plików HDFS. Interfejs wiersza poleceń obsługuje operacje systemu plików, takie jak odczyt pliku, tworzenie katalogów, przenoszenie plików, usuwanie danych i wyświetlanie listy katalogów.

Możemy biec '$HADOOP_HOME/bin/hdfs dfs -pomoc' Aby uzyskać szczegółową pomoc dotyczącą każdego polecenia. W tym przypadku „dfs” to polecenie powłoki HDFS, które obsługuje wiele podpoleceń. W obecnych wersjach Hadoop hdfs dfs jest formą preferowaną, podczas gdy starsza system plików Hadoop Polecenie wykonuje tę samą pracę dla każdego obsługiwanego systemu plików.

Poniżej wymieniono niektóre z powszechnie używanych poleceń wraz ze szczegółowymi informacjami na ich temat.

1. Skopiuj plik z lokalnego systemu plików do HDFS

$HADOOP_HOME/bin/hdfs dfs -copyFromLocal temp.txt /

To polecenie kopiuje plik temp.txt z lokalnego systemu plików do HDFS, jak pokazano poniżej.

Polecenie hdfs dfs -copyFromLocal kopiujące plik temp.txt do HDFS

2. Możemy wyświetlić listę plików znajdujących się w katalogu za pomocą polecenia -ls

$HADOOP_HOME/bin/hdfs dfs -ls /

Na poniższej liście możemy zobaczyć plik „temp.txt” (skopiowany wcześniej) w katalogu „/”.

hdfs dfs -ls wyjście wyświetlające temp.txt w katalogu głównym HDFS

3. Polecenie skopiowania pliku do lokalnego systemu plików z HDFS

$HADOOP_HOME/bin/hdfs dfs -copyToLocal /temp.txt

To polecenie odzwierciedla polecenie -get i akceptuje jawną lokalną ścieżkę docelową jako drugi argument. Poniższy wynik przedstawia plik temp.txt skopiowany do lokalnego systemu plików.

hdfs dfs -copyToLocal dane wyjściowe pokazujące plik temp.txt skopiowany do lokalnego systemu plików

4. Polecenie utworzenia nowego katalogu

$HADOOP_HOME/bin/hdfs dfs -mkdir /mydirectory

Polecenie zostanie wykonane w trybie cichym, jak pokazano poniżej.

Polecenie hdfs dfs -mkdir tworzy folder /mydirectory w HDFS

Sprawdź, czy katalog został utworzony. Teraz powinieneś wiedzieć, jak to zrobić 😉

FAQ

Duże bloki utrzymują metadane NameNode na niskim poziomie i pozwalają maperowi odczytać długi sekwencyjny ciąg bajtów przed ponownym wyszukiwaniem. Czas wyszukiwania na dysku staje się zatem niewielkim ułamkiem czasu transferu, co sprawia, że ​​skanowanie całych plików jest szybkie.

Węzeł NameNode przestaje odbierać sygnały potwierdzające, oznacza węzeł jako martwy i planuje ponowną replikację każdego bloku, który spadł poniżej jego współczynnika replikacji, na sprawne węzły danych. Zapisy w trakcie transmisji odzyskiwane są z kolejki potwierdzeń, dzięki czemu klient nie traci pakietów.

Nie znajduje się w poprawnie skonfigurowanym klastrze. HDFS High Availability uruchamia aktywny i zapasowy węzeł NameNode, które udostępniają edycję za pośrednictwem JournalNodes, a kontrolery trybu failover ZooKeeper automatycznie awansują węzeł zapasowy, gdy aktywny węzeł przestaje odpowiadać.

Obie opcje przesyłają dane do HDFS. Opcja -copyFromLocal ogranicza źródło do lokalnego systemu plików, natomiast opcja -put akceptuje dowolne obsługiwane źródło, w tym inną ścieżkę HDFS lub wejście standardowe. Poza tym działanie jest identyczne, więc opcja -copyFromLocal po prostu dokumentuje intencję.

Każdy plik, katalog i blok zajmuje pamięć w NameNode, więc miliony maleńkich plików wyczerpują się na długo przed zapełnieniem dysków. Łączenie ich w pliki sekwencyjne, archiwa Avro, ORC, Parquet lub HAR, pozwala na łatwe zarządzanie metadanymi.

Replikacja przechowuje trzy pełne kopie, co kosztuje 200% więcej pamięci. Kodowanie wymazujące, dodane w Hadoop 3, przechowuje komórki parzystości i osiąga podobną trwałość przy około 50% narzucie, kosztem tańszej pamięci masowej i wyższych kosztów procesora i sieci podczas odzyskiwania danych.

Modele uczenia maszynowego trenowane na logach audytu NameNode i metrykach DataNode mogą prognozować wyczerpanie pojemności, sygnalizować aktywne bloki i wykrywać awarie dysków, zanim zostaną one usunięte. Wykrywanie anomalii w schematach dostępu pozwala również na wczesne wykrywanie niekontrolowanych zadań.

Copilot szybko uzupełnia znane schematy org.apache.hadoop.fs, takie jak pętle FileSystem.get, FSDataInputStream i wywołania IOUtils.copyBytes. Zawsze weryfikuj generowany kod pod kątem używanej wersji Hadoop, ponieważ nazwy API i przestarzałe metody różnią się zauważalnie między Hadoop 2.x i 3.x.

Podsumuj ten post następująco: