采集日志到Hive

  • 格式:doc
  • 大小:63.50 KB
  • 文档页数:8

采集日志到Hive 2014.07.25我们现在的需求是需要将线上的日志以小时为单位采集并存储到hive 数据库中,方便以后使用mapreduce 或者impala 做数据分析。

为了实现这个目标调研了flume 如何采集数据到hive,其他的日志采集框架尚未做调研。

日志压缩flume中有个HdfsSink 组件,其可以压缩日志进行保存,故首先想到我们的日志应该以压缩的方式进行保存,遂选择了lzo 的压缩格式,HdfsSink 的配置如下:agent-1.sinks.sink_hdfs.channel=ch-1agent-1.sinks.sink_hdfs.type=hdfs agent-1.sinks.sink_hdfs.hdf s.path=hdfs://cdh1:8020/user/root/events/%Y-%m-%d agent-1.sinks.sink_hdfs.hdfs.filePrefix=logs a gent-1.sinks.sink_hdfs.hdfs.inUsePrefix=.agent-1.sinks.sink_hdfs.hdfs.rollInterval=30agent-1.sinks. sink_hdfs.hdfs.rollSize=0agent-1.sinks.sink_hdfs.hdfs.rollCount=0agent-1.sinks.sink_hdfs.hdfs.batc hSize=1000agent-1.sinks.sink_hdfs.hdfs.fileType=CompressedStream agent-1.sinks.sink_hdfs.hdf s.codeC=lzophive 目前是支持lzo 压缩的,但是要想在mapreduce 中lzo 文件可以拆分,需要通过hadoop 的api 进行手动创建索引:$ lzop a.txt$ hadoop fs -put a.txt.lzo /log/dw_srclog/sp_visit_log/ptd_ymd=20140720$ hadoop jar /usr/lib/hadoop/lib/hadoop-lzo.jar pression.lzo.LzoIndexer /log /sp_visit_log/ptd_ymd=20140720/a.txt.lzoimpala 目前也是在支持lzo 压缩格式的文件的,故采用lzo 压缩方式存储日志文件似乎是个可行方案。

自定义分隔符Hive默认创建的表字段分隔符为:\001(ctrl-A),也可以通过ROW FORMAT DELIMITED FIELDS TERMINATED BY指定其他字符,但是该语法只支持单个字符。

目前,我们的日志中几乎任何单个字符都被使用了,故没法使用单个字符作为hive 表字段的分隔符,只能使用多个字符,例如:“|||”。

使用多字符来分隔字段,则需要你自定义InputFormat来实现。

package org.apache.hadoop.mapred;import java.io.IOException;import org.apache.hadoop.io.LongWritable;import org.apache.hadoop.io.Text;import org.apache.hado op.mapred.FileSplit;import org.apache.hadoop.mapred.InputSplit;import org.apache.hadoop.mapred.J obConf;import org.apache.hadoop.mapred.LineRecordReader;import org.apache.hadoop.mapred.Rec ordReader;import org.apache.hadoop.mapred.Reporter;import org.apache.hadoop.mapred.TextInputF ormat;public class MyDemoInputFormat extends TextInputFormat{@Overridepublic RecordReader<LongWritable,Text>getRecordReader(InputSplit genericSplit,JobConf job,Reporter reporter)throws IOException{reporter.setStatus(genericSplit.toString());MyDemoRecordReader reader=new MyDemoRecordReader(new LineRecordReader(job,(FileSplit)genericSplit));return reader;}public static class MyDemoRecordReader implementsRecordReader<LongWritable,Text>{LineRecordReader reader;Text text;public MyDemoRecordReader(LineRecordReader reader){this.reader=reader;text=reader.createValue();}@Overridepublic void close()throws IOException{ reader.close();}@Overridepublic LongWritable createKey(){return reader.createKey();}@Overridepublic Text createValue(){return new Text();}@Overridepublic long getPos()throws IOException{ return reader.getPos();}@Overridepublic float getProgress()throws IOException{return reader.getProgress();}@Overridepublic boolean next(LongWritable key,Text value)throws IOException{Text txtReplace;while(reader.next(key,text)){txtReplace=new Text();txtReplace.set(text.toString().toLowerCase().replaceAll("\\|\\|\\|","\001"));value.set(txtReplace.getBytes(),0,txtReplace.getLength());return true;}return false;}}}这时候的建表语句是:create external table IF NOT EXISTS test(id string,name string)partitioned by(day string)STO RED AS INPUTFORMAT'org.apache.hadoop.mapred.MyDemoInputFormat'OUTPUTFORMAT'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'LOCATION'/log/dw_srclog/test';但是,这样建表的话,是不能识别lzo 压缩文件的,需要去扩展lzo 的DeprecatedLzoTextInputFormat 类,但是如何扩展,没有找到合适方法。

所以,在自定义分隔符的情况下,想支持lzo 压缩文件,需要另外想办法。

例如,使用SERDE 的方式:create external table IF NOT EXISTS test(id string,name string)partitioned by(day string)ROW FORMAT SERDE'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'WITH SERDEPROPER TIES('input.regex'='([^ ]*)\\|\\|\\|([^ ]*)','output.format.string'='%1$s %2$s')STORED AS IN PUTFORMAT'com.hadoop.mapred.DeprecatedLzoTextInputFormat'OUTPUTFORMAT'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'LOCATION'/log/dw_srclog/test';要想使用SERDE,必须添加hive-contrib-XXXX.jar 到classpath,在hive-env.sh 中添加下面代码;$ export HIVE_AUX_JARS_PATH=/usr/lib/hive/lib/hive-contrib-0.10.0-cdh4.7.0.jar注意:使用SERDE 时,字段类型只能为string。

这种方式建表,flume 可以将日志存储为lzo 并且hive 能够识别出数据,但是impala 中却不支持SERDE的语法,故只能放弃该方法。

最后,只能放弃lzo 压缩文件的想法,改为不做压缩。

flume 中HdfsSink 配置参数hdfs.fileType 目前只有三种可选值:CompressedStream、DataStream、SequenceFile,为了保持向后兼容便于扩展,这里使用了DataStream 的方式,不做数据压缩。

Update注意:最后又经过测试,发现impala 不支持hive 的自定义文件格式,详细说明请参考:SQL Differences Between Impala and Hive日志采集使用flume 来采集日志,只需要在应用程序服务器上安装一个agent 就可以监听文件或者目录的改变来搜集日志,但是实际情况你不一定有权限访问应用服务器,更多的方式是应用服务器将日志推送到一个中央的日志集中存储服务器。