使用Unix工具进行数据分析
该数据集中每年全球气温的最高记录是多少?我们先不使用Hadoop来回答这一问题,因为只有提供性能基准和结果检查工具,才能和Hadoop进行有效对比。
传统处理按行存储数据的工具是awk。例2-2是一个用于计算每年最高气温的程序脚本。
例2-2. 该程序从NCDC气象记录中找出每年最高气温
#!/usr/bin/env bash
for year in all/*
do
echo -ne `basename $year .gz`"\t"
gunzip -c $year | \
awk'{ temp = substr($0, 88, 5) + 0;
q = substr($0, 93, 1);
if ( temp!=9999 && q ~ /[01459]/ && temp > max) max = temp}
END { print max }'
done
该脚本循环遍历按年压缩的数据文件,首先显示年份,然后使用awk脚本处理每个文件。awk 脚本从数据中提取两个字段:气温和质量代码。气温值通过加上一个0 转换为整数。接着测试气温值是否有效(用值9999 替代NCDC 数据集中缺少的记录),通过质量代码检测读取的数值是否可疑或错误。如果数据读取正确,那么该值将与目前读取到的最大气温值进行比较,如果该值比原先的最大值大,就替换目前的最大值。处理完文件中所有的行后,再执行END块中的代码并打印出最大气温值。
下面是某次运行结果的起始部分:
% ./max_temperature.sh
1901 317
1902 244
1903 289
1904 256
1905 283
...
由于源文件中的气温值被放大了10倍,所以1901年的最高气温是 31.7°C (20世纪初记录的气温数据比较少,所以该结果是可能的)。使用亚马逊的EC2 High-CPU Extra Large Instance运行该程序,查找一个世纪以来气象数据中的最大气温值需要42分钟。
为了加快处理,我们需要并行运行部分程序。从理论上讲,这很简单:我们可以通过使用计算机上所有可用的硬件线程来处理,其中每个线程处理不同年份的数据。但是,其中依旧存在一些问题。
首先,将任务划分成大小相同的作业块通常并不容易或明显。在我们的例子中,不同年份数据文件的大小差异很大,因此部分线程会比其他线程更早运行结束。即使让它们继续下一步的工作,整个运行时间依旧由处理最长文件所需的时间决定。另一种更好的方法是将输入数据分成固定大小的块,然后把每块分配到各个进程,这样一来,即使有些进程能处理更多数据,我们也可以为它们分配更多的数据。
其次,将独立进程运行的结果合并后,可能还需要进一步的处理。在我们的例子中,每年的结果独立于其他年份,并可能将所有结果拼接起来,然后按年份进行排序。如果使用固定大小块的方法,则需要特定的方法来合并结果。在这个例子中,某年的数据通常被分割成几个块,每个块进行独立处理。我们将最终获得每个数据块中的最高气温,所以最后一步是寻找这些分块数据中的最大值作为该年的最高气温,其他年份的数据均需如此处理。
最后,我们依旧受限于一台计算机的处理能力。如果手上拥有的所有处理器都用上,至少也需要20分钟,结果也就只能这样了。我们不能使它更快。另外,某些数据集的增长会超出一台计算机的处理能力。当我们开始使用多台计算机时,整个大环境中的其他因素将对其产生影响,其中最主要的是协调性和可靠性两大因素。哪个进程负责运行整个作业?我们如何处理失败的进程?
因此,尽管可以实现并行处理,但实际上非常复杂。使用Hadoop之类的框架来实现并行数据处理将很有帮助。