我想了解如何使用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));
答案 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
答案有几个假设
不要介意多个输出文件
不关心输出的排序