HDFS handledning: Archilära, läsa & skriva Operation

⚡ Smart sammanfattning

HDFS är det distribuerade lagringslagret i Hadoop, som delar upp mycket stora filer i replikerade block över vanliga maskiner så att en enda NameNode tracks-metadata medan många DataNodes hanterar läs- och skrivförfrågningar tillförlitligt.

  • 🔘 Architecture: NameNode innehåller namnrymdsavbildningen och redigeringsloggen, medan DataNodes lagrar de faktiska blockreplikerna.
  • ☑️ Blockstorlek: Hadoop 1.x har som standard 64 MB-block; Hadoop 2.x och 3.x har istället 128 MB som standard.
  • ✅ Replikering: Tre repliker per block är standardinställningen, spridda över rack så att hårdvarufel aldrig förlorar data.
  • 🧪 Läs sökväg: FSDataInputStream och DFSInputStream hämtar blockplatser från NameNode och strömmar sedan byte direkt från DataNodes.
  • 🛠️ Skriv sökväg: DFSOutputStream köar paket, DataStreamer bygger en DataNode-pipeline och en Ack-kö skyddar mot paketförlust.
  • 🧭 Åtkomstalternativ: Filen org.apache.hadoop.fs Java API:et och hdfs dfs-skalet täcker båda öppna, läsa, skriva och stänga.

HDFS handledning

Vad är HDFS?

HDFS är ett distribuerat filsystem för lagring av mycket stora datafiler, som körs på kluster av vanlig hårdvara. Det är feltolerant, skalbart och extremt enkelt att expandera. Hadoop levereras med HDFS (Hadoop Distributed File System).

När data överstiger lagringskapaciteten på en enda fysisk maskin, blir det viktigt att dela upp det över ett antal separata maskiner. Ett filsystem som hanterar lagringsspecifika operationer över ett nätverk av maskiner kallas ett distribuerat filsystem. HDFS är en sådan programvara.

HDFS Architecture

Ett HDFS-kluster består huvudsakligen av en NameNode som hanterar filsystemets metadata och DataNoder som lagrar de faktiska uppgifterna.

  • NameNode: NameNode kan betraktas som systemets master. Den underhåller filsystemträdet och metadata för alla filer och kataloger som finns i systemet. Två filer, "namnrymdsbilden" och "redigeringsloggen", används för att lagra metadatainformation. NameNode har kännedom om alla DataNodes som innehåller datablock för en given fil, men den lagrar inte blockplatser permanent. Denna information rekonstrueras varje gång från DataNodes när systemet startas.
  • DataNode: DataNodes är slavar som finns på varje maskin i ett kluster och tillhandahåller den faktiska lagringen. De ansvarar för att hantera läs- och skrivförfrågningar från klienterna.

Eftersom en ensam NameNode skulle vara en enda felpunkt, kör nuvarande kluster en aktiv NameNode tillsammans med en standby-NameNode som delar redigeringsloggen genom ett kvorum av JournalNodes, med automatisk redundansväxling mellan de två.

Läs- och skrivoperationer i HDFS utförs på blocknivå. Datafiler i HDFS är uppdelade i blockstora bitar som lagras som oberoende enheter. Standardblockstorleken är 64 MB i Hadoop 1.x. Från och med Hadoop 2.x är standard dfs.blocksize är 128 MB.

HDFS använder ett koncept för datareplikering där flera repliker av datablock skapas och distribueras på noder i ett kluster för att möjliggöra hög tillgänglighet av data i händelse av nodfel. Standardreplikeringsfaktorn är tre (dfs.replikering), och när en DataNode slutar skicka hjärtslag replikerar NameNode automatiskt sina block någon annanstans.

Vet du? En fil i HDFS, som är mindre än ett enda block, upptar inte ett blocks fulla lagringsutrymme.

Läsa Operation i HDFS

En dataläsningsbegäran hanteras av HDFS, NameNode och DataNodes. Låt oss kalla läsaren för en "klient". Diagrammet nedan visar filläsningsoperationen i Hadoop.

HDFS läsoperationsdataflöde mellan klient, NameNode och DataNodes

  1. En klient initierar en läsförfrågan genom att anropa metoden 'open()' för FileSystem-objektet; det är ett objekt av typen DistributedFileSystem.
  2. Detta objekt ansluter till NameNode med hjälp av RPC och hämtar metadatainformation, såsom platserna för filens block. Observera att dessa adresser är för de första blocken i en fil.
  3. Som svar på denna metadatabegäran returneras adresserna till de DataNodes som har en kopia av det blocket.
  4. När adresserna för DataNodes har mottagits returneras ett objekt av typen FSDataInputStream till klienten. FSDataInputStream innehåller DFSInputStream som hanterar interaktioner med DataNode och NameNode. I steg 4 som visas i diagrammet ovan anropar en klient metoden 'read()' vilket gör att DFSInputStream upprättar en anslutning till den första DataNode som innehåller det första blocket i en fil.
  5. Data läses i form av strömmar där klienten anropar metoden 'read()' upprepade gånger. Denna process i read()-operationen fortsätter tills den når slutet av blocket.
  6. När slutet av ett block har nåtts stänger DFSInputStream anslutningen och går vidare för att hitta nästa DataNode för nästa block.
  7. När klienten har läst klart anropar den close()-metoden.

Skriva Operation i HDFS

I det här avsnittet kommer vi att förstå hur data skrivs till HDFS via filer. Diagrammet nedan traces som skriver sökvägen.

HDFS-skrivoperationspipeline med DataQueue, DataStreamer och Ack Queue

  1. En klient initierar en skrivoperation genom att anropa metoden 'create()' för DistributedFileSystem-objektet, vilket skapar en ny fil – steg nr 1 i diagrammet ovan.
  2. DistributedFileSystem-objektet ansluter till NameNode med ett RPC-anrop och initierar skapandet av en ny fil. Denna filskapandeåtgärd associerar dock inga block med filen. Det är NameNodes ansvar att verifiera att filen (som skapas) inte redan finns och att klienten har rätt behörighet att skapa en ny fil. Om en fil redan finns eller om klienten inte har tillräcklig behörighet att skapa en ny fil, utlöses ett IOException till klienten. Annars lyckas åtgärden och en ny post för filen skapas av NameNode.
  3. När en ny post i NameNode har skapats returneras ett objekt av typen FSDataOutputStream till klienten. En klient använder det för att skriva data till HDFS. Dataskrivningsmetoden anropas (steg 3 i diagrammet).
  4. FSDataOutputStream innehåller ett DFSOutputStream-objekt som hanterar kommunikationen med DataNodes och NameNode. Medan klienten fortsätter att skriva data fortsätter DFSOutputStream att skapa paket med dessa data. Dessa paket placeras i en kö som kallas DataQueue.
  5. Det finns ytterligare en komponent som heter DataStreamer som förbrukar denna DataQueue. DataStreamer frågar också NameNode om allokering av nya block, och väljer därmed önskade DataNodes som ska användas för replikering.
  6. Nu börjar replikeringsprocessen genom att skapa en pipeline med hjälp av DataNodes. I vårt fall har vi valt en replikeringsnivå på 3 och därför finns det 3 DataNoder i pipelinen.
  7. DataStreamern häller paket i den första DataNoden i pipelinen.
  8. Varje DataNode i en pipeline lagrar det mottagna paketet och vidarebefordrar detsamma till den andra DataNode i pipelinen.
  9. En annan kö, 'Ack Queue', underhålls av DFSOutputStream för att lagra paket som väntar på bekräftelse från DataNodes.
  10. När bekräftelse för ett paket i kön har tagits emot från alla DataNoder i pipelinen tas det bort från "Ack Queue". I händelse av något DataNode-fel, används paket från denna kö för att återinitiera operationen.
  11. När en klient är klar med att skriva data anropar den close()-metoden (steg 9 i diagrammet). Anropet till close() resulterar i att de återstående datapaketen spolas till pipelinen, följt av att man väntar på bekräftelse.
  12. När en slutlig bekräftelse har mottagits kontaktas NameNode för att meddela att filskrivningen är klar.

Åtkomst till HDFS med hjälp av Java API

I det här avsnittet försöker vi förstå Java gränssnitt som används för att komma åt Hadoops filsystem.

För att kunna interagera med Hadoops filsystem programmatiskt tillhandahåller Hadoop flera Java klasser. Paketet org.apache.hadoop.fs innehåller klasser som är användbara för att manipulera en fil i Hadoops filsystem. Dessa operationer inkluderar öppna, läsa, skriva och stänga. Hadoops fil-API är generiskt och kan utökas för att interagera med andra filsystem än HDFS.

Läser en fil från HDFS, programmatiskt

Objekt java.net.URL används för att läsa innehållet i en fil. Till att börja med måste vi göra Java känna igen Hadoops hdfs URL schema. Detta görs genom att anropa mängdenURLStreamHandlerFactory-metoden på URL objektet och skickar en instans av FsUrlStreamHandlerFactory till det. Den här metoden behöver bara köras en gång per JVM, därför är den innesluten i ett statiskt block.

En exempelkod är-

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);
        }
    }
}

Den här koden öppnar och läser innehållet i en fil. Sökvägen till filen på HDFS skickas till programmet som ett kommandoradsargument.

Åtkomst till HDFS med hjälp av kommandoradsgränssnittet

Detta är ett av de enklaste sätten att interagera med HDFS. Kommandoradsgränssnittet har stöd för filsystemsåtgärder som att läsa en fil, skapa kataloger, flytta filer, ta bort data och lista kataloger.

Vi kan springa '$HADOOP_HOME/bin/hdfs dfs -help' för att få detaljerad hjälp med varje kommando. Här är 'dfs' ett skalkommando för HDFS som stöder flera underkommandon. I nuvarande Hadoop-versioner hdfs dfs är den föredragna formen, medan den äldre hadoop fs kommandot utför samma arbete för alla filsystem som stöds.

Några av de ofta använda kommandona listas nedan tillsammans med några detaljer om var och en.

1. Kopiera en fil från det lokala filsystemet till HDFS

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

Det här kommandot kopierar filen temp.txt från det lokala filsystemet till HDFS, som utdata nedan visar.

hdfs dfs -copyFromLocal-kommandot kopierar temp.txt till HDFS

2. Vi kan lista filer som finns i en katalog med hjälp av -ls

$HADOOP_HOME/bin/hdfs dfs -ls /

I listan nedan kan vi se filen 'temp.txt' (kopierad tidigare) under katalogen ' / '.

hdfs dfs -ls utdata som listar temp.txt i HDFS rotkatalog

3. Kommando för att kopiera en fil till det lokala filsystemet från HDFS

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

Det här kommandot speglar -get och accepterar en explicit lokal målsökväg som ett andra argument. Utdata nedan visar temp.txt kopierad till det lokala filsystemet.

hdfs dfs -copyToLocal utdata som visar temp.txt kopierad till det lokala filsystemet

4. Kommando för att skapa en ny katalog

$HADOOP_HOME/bin/hdfs dfs -mkdir /mydirectory

Kommandot slutförs tyst, som prompten nedan visar.

hdfs dfs -mkdir-kommandot skapar mappen /mydirectory i HDFS

Kontrollera om katalogen har skapats eller inte. Nu borde du veta hur man gör det 😉

Vanliga frågor

Stora block håller NameNode-metadata små och låter en mapper läsa en lång sekventiell serie byte innan den söker igen. Disksökningstiden blir därför en liten bråkdel av överföringstiden, vilket är det som gör fullständiga filskanningar snabba.

NameNode slutar ta emot hjärtslag, markerar noden som död och schemalägger omreplikering av varje block som understigit dess replikeringsfaktor till felfria DataNodes. Skrivningar under färd återställs från Ack-kön, så att klienten inte förlorar paket.

Inte i ett korrekt konfigurerat kluster. HDFS High Availability kör en aktiv och en standby-NameNode som delar redigeringar via JournalNodes, och ZooKeeper-redundansstyrenheter uppgraderar standby automatiskt när den aktiva noden slutar svara.

Båda laddar upp data till HDFS. Alternativet -copyFromLocal begränsar källan till det lokala filsystemet, medan -put accepterar alla källor som stöds, inklusive en annan HDFS-sökväg eller stdin. Beteendet är annars identiskt, så -copyFromLocal dokumenterar helt enkelt avsikt.

Varje fil, katalog och block upptar minne i NameNode, så miljontals små filer förbrukar heapen långt innan diskarna fylls. Genom att kombinera dem till sekvensfiler, Avro-, ORC-, Parquet- eller HAR-arkiv, blir metadata hanterbar.

Replikering behåller tre fullständiga kopior, vilket kostar 200 procent extra lagringsutrymme. Raderingskodning, som lades till i Hadoop 3, lagrar istället paritetsceller och uppnår liknande hållbarhet vid ungefär 50 procents overhead, vilket byter billigare lagring mot högre CPU- och nätverkskostnader under återställning.

Maskininlärningsmodeller som tränas på NameNode-granskningsloggar och DataNode-mätvärden kan prognostisera kapacitetsutmattning, flagga hot blocks och upptäcka felaktiga diskar innan de slutar fungera. Avvikelsedetektering i åtkomstmönster avslöjar också skenande jobb tidigt.

Copilot slutför snabbt den välbekanta standardversionen av org.apache.hadoop.fs, såsom FileSystem.get, FSDataInputStream-loopar och IOUtils.copyBytes-anrop. Verifiera alltid genererad kod mot den Hadoop-version som används, eftersom API-namn och föråldrade metoder skiljer sig märkbart mellan Hadoop 2.x och 3.x.

Sammanfatta detta inlägg med: