Hadoop MapReduce példa: Első Java Program a Code

⚡ Okos összefoglaló

A Hadoop MapReduce programok háromféleképpen írhatók meg: Java osztályokat, egy leképezőt, egy reduktort és egy illesztőprogramot, amelyeket lefordítanak, egy jar-ba csomagolnak, és elküldenek a klaszternek az országonkénti eladások számlálásához.

  • 🔘 Adatbázis: A SalesJan2009.csv fájl soronként egy tranzakciót tartalmaz, az ország a nyolcadik, vesszővel elválasztott oszlopban szerepel.
  • ☑️ Térképkészítő: A SalesMapper felosztja az egyes sorokat, és kiírja az országot az állandó értékkel párosítva.
  • ✅ Csökkentő: A SalesCountryReducer egyetlen gyakorisági számmá összegzi az egyes országokba érkezőket.
  • 🧪 Vezető: A SalesCountryDriver elnevezi a feladatot, deklarálja a kulcs- és értéktípusokat, majd összekapcsolja a két osztályt.
  • 🇧🇷 Épít: Fordítsd le javac-kal, adj hozzá egy Main-Class manifest bejegyzést, majd csomagolj be mindent jar cfm-mel.
  • ⚠️ Fuss: Másold a CSV-t a HDFS-be, küldd el a jar fájlt, és olvasd be a part-00000 részt a kimeneti könyvtárból.

Hadoop MapReduce példa az első létrehozására Java program

Ebben az oktatóanyagban megtanulja a Hadoop használatát a MapReduce példákkal. A felhasznált bemeneti adat a ÉrtékesítésJan2009.csv. Értékesítéssel kapcsolatos információkat tartalmaz, például a termék nevét, árát, fizetési módját, az ügyfél városát és országát. A cél az egyes országokban eladott termékek számának meghatározása.

Az első Hadoop MapReduce program

Most ebben MapReduce oktatóanyag, létrehozzuk az elsőt Java MapReduce program:

Az alábbi képernyőkép a nyers SalesJan2009 adatokat mutatja, ahol minden sor egy tranzakciót jelöl, az ország pedig a nyolcadik, vesszővel elválasztott oszlopban található.

A SalesJan2009 értékesítési adatait egy táblázatban nyittuk meg, amely tranzakciós oszlopokat mutat.

Győződjön meg róla, hogy telepítve van a Hadoop. Mielőtt elkezdené a tényleges folyamatot, módosítsa a felhasználót „hduser”-re (a Hadoop konfigurálásakor használt azonosító – átválthat a saját Hadoop konfigurációja során használt felhasználói azonosítóra).

su - hduser_

A prompt a hduser fiókra változik, az alábbiak szerint.

Terminál prompt a hduser fiókra váltás után

1. lépés) Hozza létre a projektkönyvtárat és a forrásfájlokat

Hozz létre egy új könyvtárat MapReduceTutorial néven, ahogy az az alábbi MapReduce példában látható.

sudo mkdir MapReduceTutorial

mkdir parancs a MapReduceTutorial könyvtár létrehozásához

Adjon engedélyeket

sudo chmod -R 777 MapReduceTutorial

A chmod parancs teljes jogosultságokat ad a MapReduceTutorialhoz

Hozd létre a hármat Java forrásfájlok a MapReduceTutorial alatt. Megjegyzendő, hogy mindhárom a régebbi verziót használja. org.apache.hadoop.mapred API, amely továbbra is a Hadoop 3.x-szel együtt érkezik.

SalesMapper.java

package SalesCountry;

import java.io.IOException;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.*;

public class SalesMapper extends MapReduceBase implements Mapper <LongWritable, Text, Text, IntWritable> {
	private final static IntWritable one = new IntWritable(1);

	public void map(LongWritable key, Text value, OutputCollector <Text, IntWritable> output, Reporter reporter) throws IOException {

		String valueString = value.toString();
		String[] SingleCountryData = valueString.split(",");
		output.collect(new Text(SingleCountryData[7]), one);
	}
}

SalesCountryReducer.java

package SalesCountry;

import java.io.IOException;
import java.util.*;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.*;

public class SalesCountryReducer extends MapReduceBase implements Reducer<Text, IntWritable, Text, IntWritable> {

	public void reduce(Text t_key, Iterator<IntWritable> values, OutputCollector<Text,IntWritable> output, Reporter reporter) throws IOException {
		Text key = t_key;
		int frequencyForCountry = 0;
		while (values.hasNext()) {
			// replace type of value with the actual type of our value
			IntWritable value = (IntWritable) values.next();
			frequencyForCountry += value.get();
			
		}
		output.collect(key, new IntWritable(frequencyForCountry));
	}
}

SalesCountryDriver.java

package SalesCountry;

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapred.*;

public class SalesCountryDriver {
    public static void main(String[] args) {
        JobClient my_client = new JobClient();
        // Create a configuration object for the job
        JobConf job_conf = new JobConf(SalesCountryDriver.class);

        // Set a name of the Job
        job_conf.setJobName("SalePerCountry");

        // Specify data type of output key and value
        job_conf.setOutputKeyClass(Text.class);
        job_conf.setOutputValueClass(IntWritable.class);

        // Specify names of Mapper and Reducer Class
        job_conf.setMapperClass(SalesCountry.SalesMapper.class);
        job_conf.setReducerClass(SalesCountry.SalesCountryReducer.class);

        // Specify formats of the data type of Input and output
        job_conf.setInputFormat(TextInputFormat.class);
        job_conf.setOutputFormat(TextOutputFormat.class);

        // Set input and output directories using command line arguments, 
        //arg[0] = name of input directory on HDFS, and arg[1] =  name of output directory to be created to store the output file.

        FileInputFormat.setInputPaths(job_conf, new Path(args[0]));
        FileOutputFormat.setOutputPath(job_conf, new Path(args[1]));

        my_client.setConf(job_conf);
        try {
            // Run the job 
            JobClient.runJob(job_conf);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Töltse le a fájlokat itt

Az archívum ugyanarra a három forrásfájlra bővül ki, ahogy itt is látható.

Extracted archívumlista a SalesMapper, SalesCountryReducer és SalesCountryDriver segítségével

Ellenőrizze az összes fájl engedélyeit

Hosszú lista, amely a három fájl jogosultságait mutatja Java forrás fájlok

Ha hiányoznak az „olvasási” jogosultságok, akkor adja meg azokat:

chmod parancs olvasási jogosultságot ad hozzá a Java forrás fájlok

2. lépés) A Hadoop osztályútvonal exportálása

Exportálja az osztályútvonalat az alábbi Hadoop példában látható módon.

export CLASSPATH="$HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-client-core-2.2.0.jar:$HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-client-common-2.2.0.jar:$HADOOP_HOME/share/hadoop/common/hadoop-common-2.2.0.jar:~/MapReduceTutorial/SalesCountry/*:$HADOOP_HOME/lib/*"

Az exportált osztályútvonal visszajelzésre kerül a promptnál.

Shell prompt a Hadoop CLASSPATH változó exportálása után

3. lépés) Fordítsd le a Java fájlok

Fordítsd le a Java fájlok (ezek a fájlok a Final-MapReduceHandsOn könyvtárban találhatók). Az osztályfájljaik a csomag könyvtárába kerülnek.

javac -d . SalesMapper.java SalesCountryReducer.java SalesCountryDriver.java

A javac kimenet elavult figyelmeztetést mutat fordítás közben

Ez a figyelmeztetés biztonságosan figyelmen kívül hagyható – csak azt jelzi, hogy a leképezett API elavult.

Ez a fordítás egy könyvtárat hoz létre az aktuális könyvtárban, amelynek neve a megadott csomagnév lesz. Java forrásfájlt (azaz a mi esetünkben a SalesCountry-t), és ebbe tegyük az összes lefordított osztályfájlt.

A három lefordított osztályfájlt tartalmazó SalesCountry csomagkönyvtár

4. lépés) A jegyzékfájl létrehozása

Hozz létre egy új Manifest.txt fájlt

sudo gedit Manifest.txt

Adja hozzá a következő sort:

Main-Class: SalesCountry.SalesCountryDriver

gedit ablak, amely a Manifest.txt főosztály bejegyzését mutatja

A SalesCountry.SalesCountryDriver a fő osztály neve. Kérjük, vegye figyelembe, hogy a sor végén meg kell nyomni az Enter billentyűt.

5. lépés) Csomagold be az osztályokat egy üvegbe

Hozzon létre egy Jar fájlt

jar cfm ProductSalePerCountry.jar Manifest.txt SalesCountry/*.class

jar parancs a ProductSalePerCountry.jar fájl felépítése a manifestből

Ellenőrizze, hogy létrejött-e a jar fájl

A ProductSalePerCountry.jar fájl létrehozását megerősítő címtárlista

6. lépés) Indítsa el a Hadoop-ot

Indítsa el a Hadoop-ot

$HADOOP_HOME/sbin/start-dfs.sh
$HADOOP_HOME/sbin/start-yarn.sh

7. lépés) Másolja a bemeneti fájlt a HDFS-be

Másold a SalesJan2009.csv fájlt a ~/inputMapReduce könyvtárba.

Most használd az alábbi parancsot a ~/inputMapReduce fájl HDFS-be másolásához.

$HADOOP_HOME/bin/hdfs dfs -copyFromLocal ~/inputMapReduce /

copyFromLocal parancs kimenete natív könyvtári figyelmeztetéssel

Ezt a figyelmeztetést nyugodtan figyelmen kívül hagyhatjuk.

Ellenőrizze, hogy egy fájl valóban át van-e másolva vagy sem.

$HADOOP_HOME/bin/hdfs dfs -ls /inputMapReduce

hdfs dfs -ls a SalesJan2009.csv fájlt listázza az inputMapReduce könyvtárban

8. lépés) Futtassa a MapReduce feladatot

Futtassa a MapReduce feladatot

$HADOOP_HOME/bin/hadoop jar ProductSalePerCountry.jar /inputMapReduce /mapreduce_output_sales

Konzolkimenet, miközben a SalePerCountry feladat fut a fürtön

Ezzel létrejön egy mapreduce_output_sales on kimeneti könyvtár HDFS. Ennek a könyvtárnak a tartalma országonkénti termékeladásokat tartalmazó fájl lesz.

9. lépés) Olvasd le az eredményeket

Az eredmény a parancssori felületen keresztül a következőképpen tekinthető meg:

$HADOOP_HOME/bin/hdfs dfs -cat /mapreduce_output_sales/part-00000

A hdfs dfs -cat parancs által kinyomtatott ország- és értékesítési darabszám párok

Az eredmények webes felületen is megtekinthetők, pl.

Nyisd ki http://localhost:50070/ egy webböngészőben. A Hadoop 3.x rendszeren a NameNode webes felhasználói felülete átkerült a következő portra: 9870, szóval használd http://localhost:9870/ ott helyette.

NameNode webes felület kezdőlapja böngészőben

Most válaszd a „Fájlrendszer böngészése” lehetőséget, és navigálj a /mapreduce_output_sales mappába.

A HDFS fájlböngésző, amely a mapreduce_output_sales könyvtárat mutatja

Nyissa meg az r-00000 részt

a part-r-00000 eredményfájl megnyitva a HDFS böngészőben

A SalesMapper osztály magyarázata

A feladat teljes hosszában halad, a következő három rész bemutatja, hogy mit is csinálnak valójában az egyes osztályok.

Ebben a részben a SalesMapper osztály implementációját fogjuk megérteni.

1. Először is megadjuk az osztályunk csomagnevét. A SalesCountry a csomagunk neve. Fontos megjegyezni, hogy a fordítás kimenete, a SalesMapper.class, a következő csomagnévvel ellátott könyvtárba kerül: SalesCountry.

Ezt követően a könyvtári csomagokat importáljuk.

Az alábbi pillanatkép a SalesMapper osztály egy implementációját mutatja be:

A teljes SalesMapper osztály implementációjának szerkesztői nézete

Minta Code Magyarázat:

1. SalesMapper osztálydefiníció-

public class SalesMapper extends MapReduceBase implements Mapper<LongWritable, Text, Text, IntWritable> {

Minden mapper osztályt ki kell bővíteni a MapReduceBase osztályból, és meg kell valósítania a Mapper interfészt.

2. 'térkép' függvény meghatározása-

public void map(LongWritable key,
         Text value,
OutputCollector<Text, IntWritable> output,
Reporter reporter) throws IOException

A Mapper osztály fő része egy 'map()' metódus, amely négy argumentumot fogad el.

A 'map()' metódus minden hívásakor egy kulcs-érték párt (ebben a kódban 'key' és 'value') adunk át.

A 'map()' metódus azzal kezdődik, hogy az argumentumként kapott bemeneti szöveget felosztja. Minden sort mezőkre oszt.

String valueString = value.toString();
String[] SingleCountryData = valueString.split(",");

Itt a ',' karaktert használjuk elválasztóként.

Ezután egy párt képezünk a 'SingleCountryData' tömb 7. indexénél található rekord és az '1' érték felhasználásával.

output.collect(new Text(SingleCountryData[7]), one);

A 7. indexű rekordot választjuk, mert országadatokra van szükségünk, és ez a 'SingleCountryData' tömb 7. indexén található.

Felhívjuk figyelmét, hogy a bemeneti adataink az alábbi formátumban vannak (ahol az Ország a 7. indexben szerepel, a 0 pedig a kezdőindex):

Transaction_date,Product,Price,Payment_Type,Name,City,State,Country,Account_Created,Last_Login,Latitude,Longitude

A mapper kimenete ismét egy kulcs-érték pár, amelyet az 'OutputCollector' 'collect()' metódusa bocsát ki.

A SalesCountryReducer osztály magyarázata

Ebben a részben a SalesCountryReducer osztály implementációját fogjuk megérteni.

1. Először is megadjuk az osztályunk csomagjának nevét. Az ÉrtékesítésiOrszág a csomagunk neve. Fontos megjegyezni, hogy a fordítás kimenete, a SalesCountryReducer.class, a következő csomagnévvel ellátott könyvtárba kerül: ÉrtékesítésiOrszág.

Ezt követően a könyvtári csomagokat importáljuk.

Az alábbi pillanatkép a SalesCountryReducer osztály egy implementációját mutatja be:

A teljes SalesCountryReducer osztály implementációjának szerkesztői nézete

Code Magyarázat:

1. SalesCountryReducer osztály definíció-

public class SalesCountryReducer extends MapReduceBase implements Reducer<Text, IntWritable, Text, IntWritable> {

Itt az első két adattípus, a „Text” és az „IntWritable” a reduktor bemeneti kulcsértékének adattípusa.

A mapper kimenete a következő formában van: , A mapper ezen kimenete a reduktor bemenetévé válik. Tehát az adattípusának megfelelően a Text és az IntWritable adattípust használjuk itt.

Az utolsó két adattípus, a „Text” és az „IntWritable” a reduktor által kulcs-érték pár formájában generált kimenet adattípusa.

Minden reducer osztályt ki kell bővíteni a MapReduceBase osztályból, és meg kell valósítania a Reducer interfészt.

2. A 'csökkentési' függvény meghatározása-

public void reduce( Text t_key,
             Iterator<IntWritable> values,                           
             OutputCollector<Text,IntWritable> output,
             Reporter reporter) throws IOException {

A reduce() metódus bemenete egy kulcs, amely több értékből álló listát tartalmaz.

Például a mi esetünkben az lesz,

, , , , , .

Ezt a reduktornak a következőképpen adjuk meg:

Tehát az ilyen alakú argumentumok elfogadásához az első két adattípust használjuk, nevezetesen a Text és az Iterator adattípust. A szöveg a kulcs és az iterátor adattípusa. egy adattípus, amely az adott kulcs értékeinek listáját tartalmazza.

A következő argumentum OutputCollector típusú. amely összegyűjti a redukáló fázis kimenetét.

A reduce() metódus a kulcsérték másolásával és a frekvenciaszámláló 0-ra való inicializálásával kezdődik.

Text key = t_key;
int frequencyForCountry = 0;

Ezután a 'while' ciklus segítségével végigmegyünk a kulcshoz tartozó értékek listáján, és az összes érték összegzésével kiszámítjuk a végső gyakoriságot.

 while (values.hasNext()) {
            // replace type of value with the actual type of our value
            IntWritable value = (IntWritable) values.next();
            frequencyForCountry += value.get();
            
        }

Most az eredményt kulcs és a kapott frekvenciaszámláló formájában a kimeneti gyűjtőbe küldjük.

Az alábbi kód ezt teszi-

output.collect(key, new IntWritable(frequencyForCountry));

A SalesCountryDriver osztály magyarázata

Ebben a szakaszban a SalesCountryDriver osztály implementációját fogjuk megérteni.

1. Először is adjuk meg az osztályunk csomagnevét. A SalesCountry a csomagunk neve. Fontos megjegyezni, hogy a fordítás kimenete, a SalesCountryDriver.class, a következő csomagnévvel ellátott könyvtárba kerül: SalesCountry.

Itt van egy sor, amely megadja a csomag nevét, majd a kódot a könyvtári csomagok importálásához.

A SalesCountryDriver csomagdeklarációja és importnyilatkozatai

2. Határozzon meg egy illesztőprogram-osztályt, amely új ügyfélfeladatot, konfigurációs objektumot hoz létre, és hirdeti a Mapper és Reducer osztályokat.

A vezetői osztály felelős a MapReduce munkánk beindításáért HadoopEbben az osztályban megadjuk a feladat nevét, a bemenet/kimenet adattípusát, valamint a leképező és reduktor osztályok nevét.

Illesztőprogramkód beállítása a feladat nevéhez, kulcs- és értékosztályaihoz, valamint formátumaihoz

3. Az alábbi kódrészletben bemeneti és kimeneti könyvtárakat állítunk be, amelyek a bemeneti adatkészlet felhasználására és a kimenet előállítására szolgálnak.

Az arg[0] és az arg[1] a MapReduce gyakorlati használatában kiadott parancsokkal átadott parancssori argumentumok, azaz

$HADOOP_HOME/bin/hadoop jar ProductSalePerCountry.jar /inputMapReduce /mapreduce_output_sales

Illesztőprogram kódja, amely a bemeneti és kimeneti útvonalakat továbbítja a parancssorból.

4. Indítsuk el munkánkat

Az alábbi kód elindítja a MapReduce feladat végrehajtását -

try {
    // Run the job 
    JobClient.runJob(job_conf);
} catch (Exception e) {
    e.printStackTrace();
}

GYIK

Mindhárom osztály importálja az org.apache.hadoop.mapred nevű eredeti MapReduce API-t. A Hadoop 3.x továbbra is telepítve van és futtatja, de az új munkák általában az org.apache.hadoop.mapreduce-re vonatkoznak, amely a JobConf és a JobClient helyét a Configuration és a Job értékekre cseréli.

A korábbi feladatelőzményeken alapuló modellek megjósolják a futási időt, javaslatokat tesznek a felosztási méretekre és a redukálók számára, valamint észlelik az eltérést a futás befejezése előtt. Emellett megjelölik azokat a feladatokat is, amelyek kiömlött rekordok vagy sikertelen feladatok számlálói a szokásos tartományon kívül esnek.

A Copilot jól elvégzi az ismétlődő részeket: osztályaláírások, generikus kódok, importálások és az illesztőprogram-konfigurációs hívások. Az üzleti logikát, például azt, hogy melyik oszlop tartalmazza az országot, a fejlesztőnek továbbra is ellenőriznie kell a valódi sémával szemben.

A Hadoop nem hajlandó egy meglévő kimeneti könyvtárba írni, így a kész eredmények soha nem kerülnek felülírásra. Töröld rekurzívan a mapreduce_output_sales fájlt a hdfs dfs -rm -r paranccsal, vagy adj át egy másik kimeneti útvonalat a következő futtatáskor.

A jar eszköz figyelmen kívül hagyja a sorzáró nélküli utolsó manifest sort, így a Main-Class objektumot csendben eldobja. A jar objektum ezután hiba nélkül felépül, de futási időben meghiúsul, mivel nincs rögzítve main osztály.

Igen. A példa minden jar fájl nevében a 2.2.0-s verziót pineli. Egy másik kiadásban helyettesítsd be ezt a verziót, vagy egyszerűen használd a hadoop classpath kimenetét, amely kinyomtatja a telepített disztribúcióhoz szükséges összes jar fájlt.

Nem. Egy egycsomópontos pszeudo-elosztott telepítés változatlanul futtatja, mivel a parancsok csak a HDFS és a YARN elindítását feltételezik. Ugyanaz a jar fájl egy valódi többcsomópontos fürtnek is elküldi a kódot változtatás nélkül.

Változtasd meg a tömbindexet a leképezőben 7-ről 5-re, mivel a City a SalesJan2009.csv fájl hatodik oszlopa. Fordítsd újra, építsd újra a jar fájlt, és futtasd a feladatot egy friss kimeneti könyvtáron.

Foglald össze ezt a bejegyzést a következőképpen: