Introdução
Na era dos dinossauros, um destemido caçador de dinossauros chamado Alex embarca em uma emocionante missão para desvendar os segredos dessas criaturas pré-históricas. O objetivo de Alex é reunir dados valiosos de várias fontes e realizar análises avançadas para obter insights sobre o comportamento, a dieta e a evolução de diferentes espécies de dinossauros.
Para conseguir isso, Alex precisa aproveitar o poder do Hadoop MapReduce e sua capacidade de realizar operações de join (junção) de forma eficiente. Ao juntar dados de múltiplas fontes, Alex pode combinar informações sobre fósseis de dinossauros, suas localizações geológicas e condições ambientais para traçar um quadro abrangente do mundo dos dinossauros.
Configurar o Ambiente e os Dados
Nesta etapa, configuraremos o ambiente necessário e prepararemos os dados para a operação de join (junção).
Primeiro, altere o usuário para hadoop e, em seguida, mude para o diretório home do usuário hadoop:
su - hadoop
Crie um novo diretório chamado join-lab para armazenar nossos arquivos:
mkdir join-lab
cd join-lab
Em seguida, vamos criar dois arquivos de dados: dinosaurs.txt e locations.txt. Esses arquivos conterão informações sobre dinossauros e suas localizações de fósseis, respectivamente.
Crie dinosaurs.txt com o seguinte conteúdo:
trex,Tyrannosaurus Rex,carnivore
velociraptor,Velociraptor,carnivore
brachiosaurus,Brachiosaurus,herbivore
stegosaurus,Stegosaurus,herbivore
Crie locations.txt com o seguinte conteúdo:
trex,North America
velociraptor,Asia
brachiosaurus,Africa
stegosaurus,North America
Finalmente, faça o upload de join-lab para hdfs usando o seguinte comando:
hadoop fs -mkdir -p /home/hadoop
hadoop fs -put /home/hadoop/join-lab /home/hadoop/
Implementar a Operação Join
Nesta etapa, implementaremos um job (tarefa) MapReduce para realizar uma operação de join (junção) nos arquivos dinosaurs.txt e locations.txt.
Crie um novo arquivo Java chamado JoinDinosaurs.java no diretório /home/hadoop/join-lab com o seguinte conteúdo:
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class JoinDinosaurs {
public static class JoinMapper extends Mapper<LongWritable, Text, Text, Text> {
private final Text outKey = new Text();
private final Text outValue = new Text();
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String line = value.toString();
String[] parts = line.split(",");
if (parts.length == 2) { // locations.txt
outKey.set(parts[0]);
outValue.set("LOC:" + parts[1]);
} else if (parts.length == 3) { // dinosaurs.txt
outKey.set(parts[0]);
outValue.set("DIN:" + parts[1] + "," + parts[2]);
}
context.write(outKey, outValue);
}
}
public static class JoinReducer extends Reducer<Text, Text, Text, Text> {
private final Text outValue = new Text();
@Override
protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
Map<String, String> dinMap = new HashMap<>();
StringBuilder locBuilder = new StringBuilder();
for (Text value : values) {
String valStr = value.toString();
if (valStr.startsWith("DIN:")) {
dinMap.put("DIN", valStr.substring(4));
} else if (valStr.startsWith("LOC:")) {
locBuilder.append(valStr.substring(4)).append(",");
}
if (locBuilder.length() > 0) {
locBuilder.deleteCharAt(locBuilder.length() - 1);
}
}
StringBuilder outBuilder = new StringBuilder();
for (Map.Entry<String, String> entry : dinMap.entrySet()) {
outBuilder.append(entry.getValue()).append("\t").append(locBuilder.toString().trim());
}
outValue.set(outBuilder.toString());
context.write(key, outValue);
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
if (args.length != 2) {
System.err.println("Usage: JoinDinosaurs <input_dir> <output_dir>");
System.exit(1);
}
Job job = Job.getInstance();
job.setJarByClass(JoinDinosaurs.class);
job.setJobName("Join Dinosaurs");
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
job.setMapperClass(JoinMapper.class);
job.setReducerClass(JoinReducer.class);
job.setInputFormatClass(TextInputFormat.class);
job.setOutputFormatClass(TextOutputFormat.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
Este código define um job MapReduce com um JoinMapper e JoinReducer personalizados. O mapper lê os dados de entrada de dinosaurs.txt e locations.txt e emite pares chave-valor com o nome do dinossauro como chave e o tipo de dado ("DIN" ou "LOC") junto com o valor correspondente. O reducer então realiza a operação de join (junção) agrupando os valores por chave e combinando as informações do dinossauro com a localização.
Para compilar o código, execute o seguinte comando:
mkdir classes
javac -source 8 -target 8 -cp "/home/hadoop/hadoop/share/hadoop/common/hadoop-common-3.3.6.jar:/home/hadoop/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-core-3.3.6.jar:/home/hadoop/hadoop/share/hadoop/common/lib/*" -d classes JoinDinosaurs.java
jar -cvf join-dinosaurs.jar -C classes/ .
Em seguida, execute o job MapReduce usando o seguinte comando:
hadoop jar join-dinosaurs.jar JoinDinosaurs /home/hadoop/join-lab /home/hadoop/join-lab/output
Este comando executa a classe JoinDinosaurs do arquivo join-dinosaurs.jar, com o diretório de entrada /home/hadoop/join-lab (contendo dinosaurs.txt e locations.txt) e o diretório de saída /home/hadoop/join-lab/output.
Após a conclusão bem-sucedida do job, você pode visualizar a saída no diretório /home/hadoop/join-lab/output.
Analisar a Saída
Nesta etapa, analisaremos a saída da operação de join (junção) para obter insights sobre o mundo dos dinossauros.
Primeiro, vamos verificar o conteúdo do diretório de saída:
hadoop fs -ls /home/hadoop/join-lab/output
hadoop fs -cat /home/hadoop/join-lab/output/part-r-00000
Você deve ver uma saída semelhante à seguinte:
brachiosaurus Brachiosaurus,herbivore Africa
stegosaurus Stegosaurus,herbivore North America
trex Tyrannosaurus Rex,carnivore North America
velociraptor Velociraptor,carnivore Asia
Esta saída mostra os dados unidos, com cada linha contendo o nome do dinossauro, seus detalhes (espécie e dieta) e a localização onde seus fósseis foram encontrados.
Com base na saída, podemos fazer as seguintes observações:
- O
Tyrannosaurus Rex(T-Rex) e oVelociraptoreram dinossauros carnívoros, enquanto oBrachiosauruse oStegosauruseram herbívoros. - Os fósseis de
Brachiosaurusforam encontrados na África, os fósseis deStegosauruseTyrannosaurus Rexforam encontrados na América do Norte, e os fósseis deVelociraptorforam encontrados na Ásia.
Esses insights podem ajudar os paleontólogos a entender melhor a distribuição, o comportamento e a evolução de diferentes espécies de dinossauros em diferentes regiões geológicas.
Resumo
Neste laboratório, exploramos a implementação de uma operação de join (junção) usando Hadoop MapReduce. Ao combinar dados de múltiplas fontes, fomos capazes de obter insights valiosos sobre o mundo dos dinossauros, incluindo suas espécies, dietas e locais de fósseis.
O laboratório introduziu o conceito de junção de dados usando MapReduce, onde o mapper prepara os dados para a operação de join (junção), e o reducer realiza a junção real, agrupando os valores por chave e combinando as informações.
Através da experiência prática de configurar o ambiente, preparar os dados, implementar o job (tarefa) MapReduce e analisar a saída, adquirimos conhecimento prático de como aproveitar os poderosos recursos de processamento de dados do Hadoop para resolver problemas analíticos complexos.
Este laboratório não apenas fortaleceu nossa compreensão das operações de join (junção), mas também reforçou nossas habilidades em trabalhar com Hadoop MapReduce, escrever código Java e executar comandos em um ambiente Linux. A experiência de projetar e implementar uma solução completa do zero foi inestimável e, sem dúvida, contribuirá para nosso crescimento como engenheiros de dados ou cientistas de dados.



