Hadoop & Mapreduce Voorbeelden: Maak het eerste programma in Java

In deze tutorial leer je Hadoop gebruiken met MapReduce-voorbeelden. De gebruikte invoergegevens zijn VerkoopJan2009.csv. Het bevat verkoopgerelateerde informatie zoals productnaam, prijs, betalingsmodus, stad, land van de klant enz. Het doel is om Ontdek het aantal verkochte producten in elk land.

Eerste Hadoop MapReduce-programma

Nu in dit MapReduce-tutorial, zullen we ons eerste Java MapReduce-programma maken:

Eerste Hadoop MapReduce-programma

Gegevens van verkoopjanuari 2009

Zorg ervoor dat Hadoop is geïnstalleerd. Voordat u met het eigenlijke proces begint, wijzigt u de gebruiker in 'hduser' (id gebruikt tijdens de Hadoop-configuratie, u kunt overschakelen naar de user-id die wordt gebruikt tijdens uw Hadoop-programmeerconfiguratie).

su - hduser_

Eerste Hadoop MapReduce-programma

Stap 1)

Maak een nieuwe map met naam MapReduceTutorial zoals getoond in het onderstaande MapReduce-voorbeeld

sudo mkdir MapReduceTutorial

Eerste Hadoop MapReduce-programma

Geef toestemming

sudo chmod -R 777 MapReduceTutorial

Eerste Hadoop MapReduce-programma

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

Download hier bestanden

Eerste Hadoop MapReduce-programma

Controleer de bestandsrechten van al deze bestanden

Eerste Hadoop MapReduce-programma

en als 'lees'-rechten ontbreken, verleen dan dezelfde-

Eerste Hadoop MapReduce-programma

Stap 2)

Exporteer klassenpad zoals weergegeven in het onderstaande Hadoop-voorbeeld

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/*"

Eerste Hadoop MapReduce-programma

Stap 3)

Compileren Java bestanden (deze bestanden zijn aanwezig in directory Final-MapReduceHandsOn). De klassenbestanden worden in de pakketmap geplaatst

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

Eerste Hadoop MapReduce-programma

Deze waarschuwing kan veilig worden genegeerd.

Deze compilatie maakt een map aan in een huidige map met de naam van de pakketnaam die is opgegeven in het Java-bronbestand (bijv VerkoopLand in ons geval) en plaats alle gecompileerde klassenbestanden erin.

Eerste Hadoop MapReduce-programma

Stap 4)

Maak een nieuw bestand Manifest.txt

sudo gedit Manifest.txt

voeg follo toewing lijnen ernaar,

Main-Class: SalesCountry.SalesCountryDriver

Eerste Hadoop MapReduce-programma

SalesCountry.SalesCountryDriver is de naam van de hoofdklasse. Houd er rekening mee dat u aan het einde van deze regel op de Enter-toets moet drukken.

Stap 5)

Maak een Jar-bestand

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

Eerste Hadoop MapReduce-programma

Controleer of het jar-bestand is gemaakt

Eerste Hadoop MapReduce-programma

Stap 6)

Hadoop starten

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

Stap 7)

Kopieer het bestand VerkoopJan2009.csv in ~/inputMapReduce

Gebruik nu onderstaande opdracht om te kopiëren ~/inputMapReduce naar HDFS.

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

Eerste Hadoop MapReduce-programma

We kunnen deze waarschuwing veilig negeren.

Controleer of een bestand daadwerkelijk wordt gekopieerd of niet.

$HADOOP_HOME/bin/hdfs dfs -ls /inputMapReduce

Eerste Hadoop MapReduce-programma

Stap 8)

Voer de MapReduce-taak uit

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

Eerste Hadoop MapReduce-programma

Hiermee wordt een uitvoermap gemaakt met de naam mapreduce_output_sales on HDFS. De inhoud van deze map zal een bestand zijn met de productverkopen per land.

Stap 9)

Het resultaat kan via de opdrachtinterface worden gezien als:

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

Eerste Hadoop MapReduce-programma

Resultaten kunnen ook worden bekeken via een webinterface als-

Open r in een webbrowser.

Eerste Hadoop MapReduce-programma

selecteer nu 'Blader door het bestandssysteem' en navigeer naar /mapreduce_output_sales

Eerste Hadoop MapReduce-programma

Openen onderdeel-r-00000

Eerste Hadoop MapReduce-programma

Uitleg van de SalesMapper-klasse

In dit gedeelte zullen we de implementatie ervan begrijpen SalesMapper klasse.

1. We beginnen met het opgeven van een pakketnaam voor onze klasse. VerkoopLand is een naam van ons pakket. Houd er rekening mee dat de uitvoer van compilatie, SalesMapper.class gaat naar een map met de naam van dit pakket: VerkoopLand.

Hierna importeren we bibliotheekpakketten.

Onderstaande momentopname toont een implementatie van SalesMapper klasse-

SalesMapper-klasse uitleg

Voorbeeldcode-uitleg:

1. SalesMapper-klassedefinitie-

public class SalesMapper breidt MapReduceBase uit en implementeert Mapper {

Elke mapper-klasse moet worden uitgebreid van KaartReduceBase klasse en het moet implementeren Mapper interface.

2. 'kaart'-functie definiëren-

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

Het grootste deel van de Mapper-klasse is a 'kaart()' methode die vier argumenten accepteert.

Bij elke oproep naar 'kaart()' methode, een sleutel waarde paar ('sleutel' en 'waarde' in deze code) wordt doorgegeven.

'kaart()' De methode begint met het splitsen van invoertekst die als argument wordt ontvangen. Het gebruikt de tokenizer om deze regels in woorden te splitsen.

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

Hier '' wordt gebruikt als scheidingsteken.

Hierna wordt een paar gevormd met behulp van een record op de 7e index van de array 'Enkele Landgegevens' en een waarde '1'.

output.collect(nieuwe tekst(SingleCountryData[7]), één);

We kiezen voor een record op de 7e index omdat we dat nodig hebben Land gegevens en deze bevindt zich op de 7e index in de array 'Enkele Landgegevens'.

Houd er rekening mee dat onze invoergegevens het onderstaande formaat hebben (waar Land is op 7th index, met 0 als startindex)-

Transactiedatum, Product, Prijs, Betalingstype, Naam, Stad, Staat,Land,Account_aangemaakt,Laatste_Login,Breedtegraad,Lengtegraad

Een uitvoer van mapper is opnieuw a sleutel waarde paar dat wordt uitgevoerd met behulp van 'verzamelen()' methode van 'Uitvoerverzamelaar'.

Uitleg van de SalesCountryReducer-klasse

In dit gedeelte zullen we de implementatie ervan begrijpen VerkoopLandReducer klasse.

1. We beginnen met het opgeven van een naam van het pakket voor onze klasse. VerkoopLand is een naam van ons pakket. Houd er rekening mee dat de uitvoer van compilatie, SalesCountryReducer.class gaat naar een map met de naam van dit pakket: VerkoopLand.

Hierna importeren we bibliotheekpakketten.

Onderstaande momentopname toont een implementatie van VerkoopLandReducer klasse-

SalesCountryReducer-klasse Uitleg

Code Verklaring:

1. SalesCountryReducer-klassedefinitie-

public class SalesCountryReducer breidt MapReduceBase uit en implementeert Reducer {

Hier zijn de eerste twee gegevenstypen, 'Tekst' en 'Onschrijfbaar' zijn het gegevenstype van de invoersleutelwaarde voor het reducer.

De uitvoer van mapper heeft de vorm van , . Deze uitvoer van mapper wordt invoer voor de reducer. Dus om af te stemmen op het gegevenstype, Tekst en Onschrijfbaar worden hier als gegevenstype gebruikt.

De laatste twee gegevenstypen, 'Text' en 'IntWritable', zijn gegevenstypes van uitvoer gegenereerd door reducer in de vorm van een sleutelwaardepaar.

Elke verloopklasse moet worden uitgebreid vanaf KaartReduceBase klasse en het moet implementeren reducer interface.

2. De functie 'verminderen' definiëren-

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

Een input voor de verminderen() methode is een sleutel met een lijst met meerdere waarden.

In ons geval zal het bijvoorbeeld zijn:

, , , , , .

Dit wordt gegeven aan reducer als

Om argumenten van deze vorm te accepteren, worden dus de eerste twee gegevenstypen gebruikt: viz., Tekst en Iterator. Tekst is een gegevenstype van sleutel en Iterator is een gegevenstype voor een lijst met waarden voor die sleutel.

Het volgende argument is van type UitvoerCollector die de uitvoer van de reductiefase verzamelt.

verminderen() De methode begint met het kopiëren van de sleutelwaarde en het initialiseren van de frequentietelling naar 0.

Tekstsleutel = t_key;
int frequentieForCountry = 0;

Gebruik vervolgens 'terwijl' lus doorlopen we de lijst met waarden die aan de sleutel zijn gekoppeld en berekenen we de uiteindelijke frequentie door alle waarden bij elkaar op te tellen.

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

Nu pushen we het resultaat naar de uitvoercollector in de vorm van sleutel en verkregen frequentie tellen.

Onderstaande code doet dit-

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

Uitleg van de SalesCountryDriver-klasse

In dit gedeelte zullen we de implementatie ervan begrijpen SalesLandChauffeur klasse

1. We beginnen met het opgeven van een pakketnaam voor onze klasse. VerkoopLand is een naam van ons pakket. Houd er rekening mee dat de uitvoer van compilatie, SalesCountryDriver.class gaat naar de map met de naam van dit pakket: VerkoopLand.

Hier is een regel die de pakketnaam specificeert, gevolgd door code om bibliotheekpakketten te importeren.

SalesCountryDriver Class Uitleg

2. Definieer een driverklasse die een nieuwe clienttaak en configuratieobject zal creëren en Mapper- en Reducer-klassen zal adverteren.

De stuurprogrammaklasse is verantwoordelijk voor het instellen van onze MapReduce-taak Hadoop. In deze klasse specificeren we taaknaam, gegevenstype van invoer/uitvoer en namen van mapper- en reducer-klassen.

SalesCountryDriver Class Uitleg

3. In het onderstaande codefragment stellen we invoer- en uitvoermappen in die worden gebruikt om respectievelijk de invoergegevensset te consumeren en uitvoer te produceren.

argument[0] en argument[1] zijn de opdrachtregelargumenten die worden doorgegeven met een opdracht gegeven in MapReduce hands-on, dat wil zeggen:

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

SalesCountryDriver Class Uitleg

4. Activeer onze taak

Onderstaande code start de uitvoering van MapReduce-taak-

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