sábado, 27 de junho de 2009

Hadoop+HBase, i did

Consegui, rodando e funcionando, vamos aos detalhes.

Bem, aqui para a banda tupniquim o assunto ainda não está na moda, making a long history short, o hadoop é uma implementação em java do paper do Google sobre o sistema de arquivos distribuidos para aplicação do algoritmo Map/Reduce e o Bigtable.

Basicamente a ideia é a seguinte: Os arquivos de dados ficam espalhados em um cluster de computadores, cada arquivo é quebrado em n pedaços de tamanho definido, cada pedaço fica em n nós do cluster, para garantir disponibilidade caso um nó que guarda o dado falhe. O processamento dos dados é feito por um algoritmo que mapeia as informações e outro que reduz. Se um trabalho precisar ler algum arquivo, esse trabalho é executado no mesmo computador onde os pedaços dos arquivos estão, como os arquivos estão espalhados, ele é executado paralelamente. Os dados a serem processados podem ser armazenados em arquivos texto em um "banco de dados não relacional" (HBase), que está armazenado no cluster. A figura 1 exemplifica um pouco.


Figura 1


A configuração do ambiente é um pouco complicada de início e requer um ambiente unix, eu instalei no Ubuntu e no Mac sem maiores problemas. Irei falar do processo de configuração em outro post, o sistema é composto de vários componentes, são eles: namenode, datanode, jobtracker, tasktracker, hbase-master e hbase-region-server.

O namenode é responsável pelo sistema de arquivos distribuídos. Ele guarda uma tabela que armazena informações sobre os pedaços dos arquivos e os datanodes onde eles estão armazenados. Quando uma requisição de abertura de arquivo chega ele informa para o cliente quais datanodes tem o arquivo e o cliente pede diretamente ao datanode. Se um datanode falha ele manda os outros datanodes que contem cópia dos pedações dos arquivos que estavam no que falhou se redistribuirem, ele mantém a proporção de disponibilidade do arquivo. Ele é o único ponto de falha do sistema, pos ele é que contem a imagem do sistema de arquivos distribuído.

O datanode é o lugar onde o dado está realmente armazenado. Quando um datanode entra no ar ele se conecta no namenode e aguarda novos pedaços de arquivos para armazenar e cuidar.

O jobtracker e o responsável por tratar os novos trabalhos de Mapreduce que chegaram no sistema. Quando um novo trabalho chega o jobtracker conversa com o namenode para descobrir em quais datanodes estão os pedaços dos arquivos o novo trabalho precisa e copia o trabalho para os tasktrackers que estão rodando no mesmo servidor do datanode.

O tasktracker é o responsável pela execução dos trabalhos em si, ele executa a operação de Map, mapeando os valores que deverão ser reduzidos em algum outro tasktracker ou localmente.

O hbase-master controla as tabelas do sistema e alocação dos dados.

O hbase-region-server controla uma região de dados.

Uma coisa que confunde as vezes, mesmo lendo os papers e wikis na net, é o algoritmo MapReduce. Vou tentar dar uma pequena revisão, mas para maiores detalhes é melhor o paper. Basicamente a função Map deve mapear os valores, relacionando-os a uma chave e passando para o Reduce enquanto esse reduz os valores e cria a saída final ou intermediária. Vamos ao

Exemplo:
Você deseja saber a média de salário e idades, por bairro, de toda a população do Brasil, que está armazenada, habitante por habitante, em uma tabela de alguns teras.


HABITANTES
Nome Bairro Sexo Salário Idade
nome1 bairro1 M 1000 18
nome2 bairro1 F 700 24
nome3 bairro2 M 230 19


A função Map irá gerar a informação:

Chave Valor
bairro1 => 1000, 18
bairro1 => 700, 24
bairro2 => 230, 19

Parece estranho a informação bairro1 estar duplicada, mas é assim mesmo, ela vai ser reduzida pela parte de reduce. Todos os valores para a mesma chave são passadas para o mesma instância, ou seja, a redução será executada também em paralelo. Se desejar alguma informação composta, basta gerar uma chave composta, exemplo bairro1-M para se você deseja saber por bairro/sexo.

Na verdade o processamento de dados complexos tem mais detalhes que ficam complicados somente com o MapReuce, muitas das vezes é necessário fazer pré-processamento ou junções com os dados é fazer tudo isso na mão da um bocado de trabalho, mas para isso existe o Cascade, mas esse é outro assunto que estou testando, assim que terminar os testes farei um novo post. No próximo post sobre o Hadoop irei colocar alguns exemplos de código e documenta-los, essa explicação inicial servirá como base para os póximos, nos vemos lá.







segunda-feira, 22 de junho de 2009

.Net, as coisas estranhas

Bem, tenho desenvolvido ultimamente em .Net, não vou negar, e a cada dia eu me deparo com uma coisa pior que a outra. Resolvi escreve-las aqui, não para icitar brigas, mas para documenta-las. Vamos as coisas mais estranhas do .Net.


1) Serialização de Objetos: Existe uma classe chamada XmlSerializer, muito útil, mas quando você vai serializar um objeto que se relaciona com outros você precisa criar uma instancia do XmlSerializer informando todas as classes que o seu objeto depende, ele não consegue inferir via reflexão.

é mais iu menios assim:


XmlSerializer ser = new XmlSerializer(
typeof(AClasseQueVaiSerializar), new Type[] {
typeof(todas), typeof(as), typeof(classes),
typeof(que), typeof(depende), });


Se houver outra forma e alguem souber, por favor, me avise.

2) Falta de comportamento padrão: Precisei criar um controle para exibir algumas informações para o usuário, para deixar a coisa mais bonita coloquei as bordas arredondas seguindo algumas dicas que achei na internet. Como a caria da coisa ficou legal, gerei a partir do controle uma imagem e salvei, para fazer um estilo de live preview quando o usuário selecionasse o arquivo depois de salvo. Ai é que veio a surpresa, cade os cantos arredondados????

Só para clarear, segue o trecho de código:

// Função do windows que deixa com os cantos arredondados.
[DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
private static extern IntPtr CreateRoundRectRgn(
int nLeftRect, // x-coordinate of upper-left corner
int nTopRect, // y-coordinate of upper-left corner
int nRightRect, // x-coordinate of lower-right corner
int nBottomRect, // y-coordinate of lower-right corner
int nWidthEllipse, // height of ellipse
int nHeightEllipse // width of ellipse
);
...
Region = System.Drawing.Region.FromHrgn(
CreateRoundRectRgn(0, 0, Width, Height, 20, 20));


E para salvar a imagem, simplesmente...


Bitmap bitmap = new Bitmap(Width_controle, Height_controle);
panel2.DrawToBitmap(bitmap, new Rectangle(0,0,
Width_controle, Height_controle) );


3) Emuns: Bem, são realmente simples enumerações numéricas, bem diferente do Java.