hive正则解析日志

背景
工作中接触到流量日志解析,原有的解析流程是将日志文件从存储池上传到hdfs,然后通过hadoop mr 任务去解析,解析后的数据导入特定的hive表对应的目录中。这个流程存在几个问题:

1.日志上传的过程较长,例如某业务线主站的系统45台机器,每小时一个文件,一天下来有45*24个文件,上传这部分数据要用80分钟,真正解析的时间只有20分钟,日志数据处于关键的节点数据,被很多数据任务依赖,变相降低了解析的效率。

  1. 日志解析不够灵活,例如主站的开发要再日志中加字段,如果想要将这个字段在hive中体现,那么必须要调整mr的代码。在沟通顺畅的前提下还好,往往业务开发部会通知数据开发这些变动,等到发现问题以后还要回头处理历史数据问题。
  2. 逻辑不够明确,mr解析日志的话,整个解析的逻辑封死在java代码中,后续维护这部分的人很难很快的搞明白hive表中字段的来龙去脉,特别是在解析的过程中就有字段的加工。

定时上传文件
通过脚本,定时(每隔一小时)的从日志存储池把日志上传到hdfs,在上传前需要先判断存储池中日志文件是否已经收集完毕。处理的过程中需要注意跨天的问题,将数据放入正确的分区中。

原始日志解析
这里要用hive自带的RegexSerDe来解析。
1.语法关键字

  • input.regex:输入的正则表达式
  • input.regex.case.insensitive:是否忽略字母大小写,默认为false
  • output.format.string:输出的正则表达式

2.建表语句
这部分需要注意,input.regex中需要全匹配日志的整行,每个括号表示一个字段,这里选择创建的是hive外部表。

CREATE EXTERNAL TABLE test.original_log(
log_time string COMMENT '',
log string COMMENT '日志中的json数据')
COMMENT '原始日志表'
PARTITIONED BY (
dt string COMMENT '日期分区')
ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
'input.regex'='(\[.\])\[.\]\[.\]\[.\] (\{.*\})',
'output.format.string'='%1$s')
STORED AS INPUTFORMAT
'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
'hdfs://original_log';
  1. 深度解析

经过上述的流程,原始日志已经在hive中可以查询,但是关键字段还在一个大的json字段中,再通过get_json_object方法解出来即可