Final

10
David Ferreira-72603 Gil Mesquita-72700 Jorge Loureiro-72982 12 de outubro de 2015 Complementos Base de Dados TRABALHO PRÁTICO HADOOP

description

FInal total

Transcript of Final

Page 1: Final

David Ferreira-72603 Gil Mesquita-72700 Jorge Loureiro-72982

 

Complementos Base de Dados

Page 2: Final

Introdução

O trabalho proposto é o desenvolvimento de uma aplicação, que seja capaz de processar um determinado tipo de dados definido pelo grupo, que através do Hadoop, produzirá um resultado processado. Será necessário o desenvolvimento de funções Map e Reduce, bem como otimizações, nomeadamente o desenvolvimento de uma função Combiner e a utilização de uma forma de encadeamento de jobs  (job chaining).

Por opção do grupo, a aplicação a desenvolver irá correr sobre uma instalação hadoop configurada em nó pseudo-distribuido.

PÁGINA 1

Page 3: Final

Descrição do problema

O problema desenvolvido pelo grupo aborda o número de vezes que uma pessoa vai ao ginásio durante a semana. Foram criados sete ficheiros, correspondentes ao histórico de presenças num ginásio em cada dia da semana. Com esta informação teve-se como objetivo:

1. Calcular o número de vezes que cada pessoa foi ao ginásio durante a semana.

2. Apresentar a pessoa que mais vezes foi ao ginásio durante essa mesma semana.

Solução

1º Job:

Para o primeiro objetivo, passou-se à criação de um job, foi necessária a implementação de uma função map() que vai ler o texto respetivo de cada file, linha-a-linha, tokenizando cada uma para posterior envio para a função de reduce(). Ao chegar ao reduce os tokens vão ter o formato na forma <Text, one>, sendo que one é uma variável estática inicializada com o valor “1” e Text será o token processado pela função de mapping. A função reduce vai por sua vez, processar pares, contando o número de vezes que cada nome vai ocorrer, indicando posteriormente o resultado no objeto context.

Figura 1- Função Map

A imagem anterior apresenta o código referente à função map, esta função recebe como parâmetros de entrada uma Key do tipo Object e um value do tipo Text. Através do StringTokenizer o map vai ler linha a linha e vai interpretar o seu conteúdo, apenas acabando quando já não encontrar mais nenhum token. Quando termina escreve o par no objeto contexto que irá ser enviado como input para a função de reduce.

PÁGINA 2

Page 4: Final

Figura 2- Função Reduce

A imagem a cima apresenta a função de reduce, vai receber uma key do tipo Text e um value do tipo LongWritable, sendo ambos os argumentos do mesmo tipo que os argumentos do output da função map(). Inicialmente foi criada um variável do tipo LongWritable que servirá para indicar o resultado da contagem do número de vezes que cada nome aparece, ao objeto context. Para realizar a contagem utilizou-se um ciclo for each, que vai incrementando ao valor já existente uma unidade, por cada vez que o nome é repetido.

2º Job:

Este segundo job destina-se a realizar o segundo objetivo proposto e contém tal como o primeiro job uma função de map e uma de reduce.A função de map mapeia os tokens para a função de reduce, neste caso faz o split por cada mudança de linha para um array (“lines”), iterando de seguida sobre esse mesmo array e fazendo um novo split, desta vez por cada tab presente, resultando num novo array (“array”) de dois elementos que vão assumindo sucessivamente os valores do split por tab. A criação deste split por tab foi necessária uma vez que o que é recebido no mapper através do output do reducer do primeiro job é um par na forma “<Text, value>“ mas que no entanto não passa de um Text! Uma vez que no segundo reducer queremos trabalhar com estes dados na forma <Text, value> como sendo um par de valores, foi necessário então a implementação deste split. Por cada iteração os dois elementos resultantes do último split são escritos para a variável context que é depois enviada como input para a nossa próxima função de reduce.

PÁGINA 3

Page 5: Final

Figura 3- Função Map do segundo job

A função de reduce recebe sucessivamente duas variáveis já separadas pelo map (como referido a cima), uma com o nome do sujeito e outra com o número de vezes que ele foi ao ginásio.Por cada par de variáveis recebidas, verifica se o número de presenças é o maior até ao momento e cada vez que recebe um novo máximo salvaguarda tanto o nome do sujeito como o respetivo número de presenças.

O ciclo termina quando entra na instrução decisória “if” que identifica quando é que não há mais nada a ser tratado no reducer, é neste momento que as variáveis “nome” e “nºpresenças” correspondentes ao máximo de presenças encontrado são escritas para a variável context, terminando assim a execução do job.

Figura 4- Função Reduce do segundo job

PÁGINA 4

Page 6: Final

Encadeamento

Tal como foi dito anteriormente, para concretizar o segundo objetivo passou-se à criação de um outro job, dividindo-se o problema em sub-tarefas, cada uma delas realizada por um job individual. Desta forma, tornou-se possível  encadear os jobs. Este processo pode ser realizado de diferentes formas. A forma utilizada consistiu na criação de dois jobs no mesmo programa, fazendo com que o output do primeiro job fosse o input do segundo, permitindo assim que se obtivesse a informação do primeiro job, sobre a qual o segundo utilizou para verificar qual a pessoa que mais vezes foi ao ginásio nessa semana, bem como o número de vezes que essa pessoa esteve no ginásio durante a semana. Utilizou-se o objeto JobControl, para permitir a interligação dos jobs programaticamente. O Objecto JobControl aceita instâncias de ControlledJob, o qual define um job mais as suas dependências, automaticamente interligando os outputs com os inputs necessários.

Figura 5- Primeiro job

PÁGINA 5

Page 7: Final

Figura 6- Segundo job

Figura 7-JobControl

PÁGINA 6

Page 8: Final

Otimização com Combiner

Como forma de otimização do programa, implementou-se um combiner que irá combinar a informação que será posteriormente enviada ao reducer do primeiro job, isto é, não irá enviar o par chave-valor por cada vez que verificar um nome, mas sim só depois de verificar todos os nomes que existem e número de vezes que cada um ocorre por cada ficheiro. Assim é aumentado o desempenho da aplicação. A realização desta fase ocorre entre a fase de Map e a de Reduce, e é explicitamente declarada no objeto job da mesma forma que as classes Mapper e Reducer. Como se pode verificar na imagem seguinte, o combiner é bastante semelhante à função reduce, verificando-se ainda que o job1 que contem a função combiner, demora menos a processar os dados que o job1 sem a função combiner. A diferença temporal não é muito acentuada pois está a ser processada pouca quantidade de informação, servindo este exemplo apenas para fins ilustrativos.

Figura 8- job1 sem combiner | job1 com combiner

Figura 9- Função combiner aplicada ao Job1

PÁGINA 7

Page 9: Final

PÁGINA 8