Mapreduce 分割日志文件的最佳方法

Mapreduce 分割日志文件的最佳方法,mapreduce,hive,bigdata,elastic-map-reduce,Mapreduce,Hive,Bigdata,Elastic Map Reduce,需要帮助,这似乎是一项很常见的任务: 我们每小时都有包含许多不同事件的巨大日志文件。 我们一直在使用配置单元以硬编码方式将这些事件拆分为不同的文件: from events insert overwrite table specificevent1 where events.event_type='specificevent1' insert overwrite table specificevent2 where events.event_type='specificeve

需要帮助,这似乎是一项很常见的任务: 我们每小时都有包含许多不同事件的巨大日志文件。 我们一直在使用配置单元以硬编码方式将这些事件拆分为不同的文件:

from events
  insert overwrite table specificevent1
   where events.event_type='specificevent1'
  insert overwrite table specificevent2
   where events.event_type='specificevent2'
...;
这是有问题的,因为我们添加的每个新事件的代码都必须更改

我们尝试使用动态分区进行自动解析,但遇到了以下问题:

  • 如果我的分区模式是
    /year/month/day/hour/event
    ,那么我们无法恢复超过一天的分区,因为每月的分区数将是~(30天)(24小时)(100~events)=~72k,这太多了,无法使用
  • 如果我的模式是
    event/year/month/day/hour
    ,那么由于事件是动态的部分,它会强制将下一个分区编写为动态的,这会导致随着分区数量的增加,拆分需要更多的时间

  • 有没有更好的方法(蜂巢和非蜂巢解决方案)?

    希望这能帮助其他人

    我发现,如果要将日志文件拆分为多个不同的文件(每个事件类型的文件),那么配置单元不是最佳选择。 Hive提供的动态分区有太多的限制

    我最后做的是编写一个定制的MapReduce jar。 我还发现旧的Hadoop接口更合适,因为它提供了MultipleTextOutputFormat抽象类,让您可以实现generateFileNameForKeyValue()。(新的hadoop提供了一种不同的多输出文件机制:如果您有预定义的输出位置,则多输出是很好的,但没有了解如何从键值动态地获得它们)

    示例代码:

    \*
    Run example:
    hadoop jar DynamicSplit.jar DynamicEventSplit.DynamicEventSplitMultifileMapReduce /event/US/incoming/2013-01-01-01/ event US 2013-01-01-01 2 "[a-zA-Z0-9_ ]+" "/event/dynamicsplit1/" ","
    */
    package DynamicEventSplit;
    
    import java.io.*;
    import java.util.*;
    import org.apache.hadoop.fs.Path;
    import org.apache.hadoop.conf.*;
    import org.apache.hadoop.io.*;
    import org.apache.hadoop.mapred.*;
    import org.apache.hadoop.util.*;
    import org.apache.hadoop.mapred.lib.*;
    import java.io.IOException;
    import java.util.Iterator;
    
    import org.apache.hadoop.fs.FileSystem;
    import org.apache.hadoop.mapred.JobConf;
    import org.apache.hadoop.mapred.FileOutputFormat;
    import org.apache.hadoop.mapred.RecordWriter;
    import org.apache.hadoop.mapred.Reporter;
    import org.apache.hadoop.util.Progressable;
    
    public class DynamicEventSplitMultifileMapReduce
    {
            static class Map extends MapReduceBase implements Mapper<LongWritable, Text, Text, Text>  
            {
                private String event_name;
                private String EventNameRegexp;
                private int EventNameColumnNumber;
                private String columndelimeter=",";
    
                public void configure(JobConf job)
                {
                    EventNameRegexp=job.get("EventNameRegexp");
                    EventNameColumnNumber=Integer.parseInt(job.get("EventNameColumnNumber"));
                    columndelimeter=job.get("columndelimeter");
                }
                public void map(LongWritable key, Text value,OutputCollector<Text, Text> output, Reporter reporter) throws IOException 
                {
                    //check that expected event_name field exists  
                    String [] dall=value.toString().split(columndelimeter);
                    if (dall.length<EventNameColumnNumber)
                    {
                        return;
                    }
                    event_name=dall[EventNameColumnNumber-1];
                    //check that expected event_name is valid  
                    if (!event_name.matches(EventNameRegexp))
                    {
                        return;
                    }
                    output.collect(new Text(dall[1]),value);
                }
            }
    
            static class Reduce extends MapReduceBase implements Reducer<Text, Text, Text, Text> 
            {
                public void reduce(Text key, Iterator<Text> values,OutputCollector<Text, Text> output, Reporter reporter) throws IOException 
                {
                        while (values.hasNext()) 
                        {
                            output.collect(key, values.next());
                        }
                }
            }
    
    
            static class MultiFileOutput extends MultipleTextOutputFormat<Text, Text> 
            {
                private String event_name;
                private String site;
                private String event_date;
                private String year;
                private String month;
                private String day;
                private String hour;
                private String basepath;
    
    
                public RecordWriter<Text,Text> getRecordWriter(FileSystem fs, JobConf job,String name, Progressable arg3) throws IOException
                {
                    RecordWriter<Text,Text> rw=super.getRecordWriter(fs, job, name, arg3);
                    site=job.get("site");
                    event_date=job.get("date");
                    year=event_date.substring(0,4);
                    month=event_date.substring(5,7);
                    day=event_date.substring(8,10);
                    hour=event_date.substring(11,13);
                    basepath=job.get("basepath");
                    return rw;
                }
    
                protected String generateFileNameForKeyValue(Text key, Text value,String leaf) 
                {
                    event_name=key.toString();
                    return basepath+"event="+event_name+"/site="+site+"/year="+year+"/month="+month+"/day="+day+"/hour="+hour+"/"+leaf;
                }
    
                protected Text generateActualKey(Text key, Text value) 
                {
                    return null;
                }
            }
    
            public static void main(String[] args) throws Exception 
            {
                    String InputFiles=args[0];
                    String OutputDir=args[1];
                    String SiteStr=args[2];
                    String DateStr=args[3];
                    String EventNameColumnNumber=args[4];
                    String EventNameRegexp=args[5];
                    String basepath=args[6];
                    String columndelimeter=args[7];
    
                    Configuration mycon=new Configuration();
                    JobConf conf = new JobConf(mycon,DynamicEventSplitMultifileMapReduce.class);
                    conf.set("site",SiteStr);
                    conf.set("date",DateStr);
    
                    conf.setOutputKeyClass(Text.class);
                    conf.setMapOutputKeyClass(Text.class);
                    conf.setOutputValueClass(Text.class);
    
                    conf.setMapperClass(Map.class);
                    conf.setReducerClass(Reduce.class);
    
                    conf.setInputFormat(TextInputFormat.class);
                    conf.setOutputFormat(MultiFileOutput.class);
    
                    conf.setMapSpeculativeExecution(false);
                    conf.setReduceSpeculativeExecution(false);
    
                    FileInputFormat.setInputPaths(conf,InputFiles);
                    FileOutputFormat.setOutputPath(conf,new Path("/"+OutputDir+SiteStr+DateStr+"/"));
    
                    conf.set("EventNameColumnNumber",EventNameColumnNumber);
                    conf.set("EventNameRegexp",EventNameRegexp);
                    conf.set("basepath",basepath);
                    conf.set("columndelimeter",columndelimeter);
    
                    JobClient.runJob(conf);
            }
    }
    
    \*
    运行示例:
    hadoop jar DynamicSplit.jar DynamicEventSplit.DynamicEventSplit MultifileMapReduce/event/US/incoming/2013-01-01-01/event US 2013-01-01-01-01 2“[a-zA-Z0-9][+”“/event/dynamicsplit1/”,”
    */
    包装动态裂痕;
    导入java.io.*;
    导入java.util.*;
    导入org.apache.hadoop.fs.Path;
    导入org.apache.hadoop.conf.*;
    导入org.apache.hadoop.io.*;
    导入org.apache.hadoop.mapred.*;
    导入org.apache.hadoop.util.*;
    导入org.apache.hadoop.mapred.lib.*;
    导入java.io.IOException;
    导入java.util.Iterator;
    导入org.apache.hadoop.fs.FileSystem;
    导入org.apache.hadoop.mapred.JobConf;
    导入org.apache.hadoop.mapred.FileOutputFormat;
    导入org.apache.hadoop.mapred.RecordWriter;
    导入org.apache.hadoop.mapred.Reporter;
    导入org.apache.hadoop.util.Progressable;
    公共类DynamicEventSplitmMultiFileMapReduce
    {
    静态类映射扩展MapReduceBase实现映射器
    {
    私有字符串事件名称;
    私有字符串EventNameRegexp;
    私有int事件名列号;
    私有字符串columndelimeter=“,”;
    公共无效配置(JobConf作业)
    {
    EventNameRegexp=job.get(“EventNameRegexp”);
    EventNameColumnNumber=Integer.parseInt(job.get(“EventNameColumnNumber”);
    columndelimeter=job.get(“columndelimeter”);
    }
    公共void映射(LongWritable键、文本值、OutputCollector输出、Reporter报告器)引发IOException
    {
    //检查预期的事件名称字段是否存在
    字符串[]dall=value.toString().split(columndelimeter);
    if(dall.length