Hadoop初体验

最近公司的同事把hadoop搭了起来, 主要用于计算分析日志. 很久很久以前(–_–!!!)我就对这个东东感兴趣了, 可惜一直没有机会接触, 正好趁这个机会学习下.

既然要用, 无非就是利用它通过map/reduce的思想来进行大数据的计算, 网上搜了一下, 发现了slideshare上的这篇分享(需要翻墙, 哎). 这个slide 对hadoop以及map/reduce介绍的很详细, 这里我主要基于这个slide来实践一下.

下面主要以perl程序来进行实验, 这里有个用python介绍的文章, 写的相当好, 同样强烈推荐.

map and reduce

好吧, 既然说到了hadoop, 肯定就需要了解下map/reduce. 简单来看就是分治思想. 大体的逻辑大概是这样子的;)

  • map 将输入数据转换成key => value形式
  • sort 将 map 后的结果按照key排序
  • reduce 处理 sort 后的结果, 生成最终的数据

有关map/reduce的详细介绍请猛击这里

动手

hadoop 提供了streaming模型来供任意可执行程序(需要实现map/reduce方法)来进行数据处理. 下面是一个简单实现了map/reduce的小程序. 这个程序从每行日志中获取区域以及访问次数的信息, 最后得到各个区域总的访问次数

先是 mapper, 从每行日志中抽取区域信息为key, 访问次数信息为value:

mapper.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/perl

use strict;
use 5.010;

# assume log like "area ip time work visitnum haha"

while(<>){
    chomp;
    my ($area, $visit) = process_log($_);

    next if not defined $ip or not defined $visit;

    # my $key = $ENV{map_input_file};

    print $area."\t".$visit."\n";
}

reducer 则是负责将相同的地区的访问次数进行累加汇总:

reducer.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/usr/bin/perl

use strict;
use 5.010;

my ($prev_area, $visit_cnts);

while(<>){
    chomp;

    my ($area, $cnts) = split;

    # init
    if( not defined $prev_area ){
        $prev_area = $area;
    }

    if( $area ne $prev_area ){
        output($prev_area, $visit_cnts);

        # reinit
        $visit_cnts = $cnts;
        $prev_area = $area;
    }
    else{
        $visit_cnts += $cnts;
    }
}

output($prev_area, $visit_cnts);

sub output
{
    my ($area, $cnt) = @_;

    print "$area\t$cnt\n";
}

将两个程序传到hadoop上后, 执行:

run.sh
1
2
3
4
5
6
#!/bin/bash

hadoop jar /path/of/streaming/hadoop-streaming-ver.jar \
           -file /path/of/map.pl      -mapper  'perl /path/of/map.pl' \
           -file /path/of/reduce.pl   -reducer 'perl /path/of/reduce.pl' \
           -input /path/of/input/logs          -output /path/of/output/result

这样一个任务就可以跑起来了. 当然, 这是一个最最简单的例子, 这里的关键是将计算逻辑map/reduce的方法去实现.

感受

  1. 我们的自己程序可能会想要获取当前系统或者文件相关信息, 这个时候该怎么办呢?其实这些变量都可以使用环境变量来获取, 例如我们的mapper程序想要获取当前文件的文件名, 可以通过$ENV{map_input_file}获取, 其他的变量也是如此.
  2. hadoop系统可能出各种问题(一般都是系统限制的原因, 例如硬盘内存不够用等等), 这个比较头疼.
  3. 使用起来还是很好很强大的.
  4. perl来写map/reduce可以使用相关的库来简化开发

PPPPSSSS

最近怎么感觉这么累呢…..

Comments