如何使用MapReduce处理日志文件

时间:2014-05-15 22:20:16

标签: hadoop mapreduce bigdata

我想了解如何使用MapReduce处理日志文件。

例如,如果我有这样的文件传输日志:

Start_Datestamp,file_name,source, host,file_size,transfered_size
2012-11-18 T 16:05:00.000, FileA,SourceA, HostA,1Gb, 500Mb
2012-11-18 T 16:25:00.000, FileA,SourceA, HostB,1Gb, 500Mb

2012-11-18 T 16:33:00.000, FileB,SourceB, HostB,2Gb, 2GB

2012-11-18 T 17:07:00.000, FileC,SourceC, HostA,1Gb, 500Mb
2012-11-18 T 17:19:00.000, FileB,SourceC, HostA,1Gb, 500Mb
2012-11-18 T 17:23:00.000, FileA,SourceC, HostC,1Gb, 500Mb

我希望像这样汇总和输出:

Start_Datestamp,file_name,source, Total_transfered_size
2012-11-18 T 16:00, FileA,SourceA, 1000Mb

2012-11-18 T 16:30, FileB,SourceB,  2GB

2012-11-18 T 17:00, FileC,SourceC,500Mb
2012-11-18 T 17:00, FileB,SourceC, 500Mb
2012-11-18 T 17:00, FileA,SourceC, 500Mb

如上所示,它应该以30分钟的间隔聚合文件传输。

我设法使用以下教程实现30分钟间隔聚合: http://www.informit.com/articles/article.aspx?p=2017061

但它非常简单:

Start_Datestamp,count
2012-11-18 T 16:00, 2
2012-11-18 T 16:30, 1
2012-11-18 T 17:00,3

但不确定如何使用其他字段。我尝试使用WritableComparable创建复合键来组成Start_Datestamp,file_name,source但它无法正常工作。有人可以指导我吗?

UPDATE !!

所以现在我设法使用Sudarshan建议打印多个字段。但是,我遇到了另一个问题。

例如,让我们看一下上表中的示例数据:

Start_Datestamp,file_name,source, host,file_size,transfered_size
2012-11-18 T 16:05:00.000, FileA,SourceA, HostA,1Gb, 500Mb
2012-11-18 T 16:25:00.000, FileA,SourceA, HostB,1Gb, 500Mb
2012-11-18 T 16:28:00.000, FileA,SourceB, HostB,1Gb, 500Mb

我想做的是按时间戳将数据分组30分钟间隔,来源,总和(transfered_size)

所以它想要这样:

Start_Datestamp,source, Total_transfered_size
2012-11-18 T 16:00,SourceA, 1000Mb <<==Please see those two records are now merged to '16:00' timestamp .
2012-11-18 T 16:00,SourceB, HostB,1Gb, 500Mb <<===this record should not be merged because different source, even though the timetamp is within '16:00' frame.

但在我的情况下发生的事情是只打印每个区间的第一条记录

e.g。 Start_Datestamp,source,Total_transfered_size 2012-11-18 T 16:00,SourceA,1000Mb&lt;&lt; ==只有这些记录被打印出来。另一个不打印。

在我的Map类中,我添加了以下spinets:

out = "," + src_loc + "," + dst_loc + "," + remote     + ","
+ transfer + " " + activity + ","     + read_bytes+ "," 
+ write_bytes + ","     + file_name + " " 
+ total_time + "," + finished;  

date.setDate(calendar.getTime()); 

output.collect(date, new Text(out));

然后在reducer:

String newline = System.getProperty("line.separator");
   while (values.hasNext()) { 
out += values.next().toString() + newline;
}     

output.collect(key, new Text(out));

我认为问题出在reducer迭代上。

我尝试在while循环中移动下面的代码,这似乎是打印所有记录。但我不完全确定这是否是正确的做法。任何建议将不胜感激。

output.collect(key, new Text(out));

1 个答案:

答案 0 :(得分:0)

你正走在正确的道路上,而不是在值中传递1。 custom_key将以30分钟的间隔时间

 output.collect(custom_key, one);

您可以传递整个日志文本。

output.collect(customkey, log_text);

在reducer中,您将在iterable中收到整个日志文本。在你的reducer中解析它并使用相关的字段。

map<source,datatransferred>
for loop on iterable
   parse log text line
   extract file_name,source, Total_transffered_size
   store the sum of data into the map against the source
end loop

for loop on map
    output time,source,sum calculated in above step
end loop

答案有几个假设

  1. 不要介意多个输出文件

  2. 不关心输出的排序