Hive读取不到Flume正在写入的HDFS临时文件的解决办法

本文主要是介绍Hive读取不到Flume正在写入的HDFS临时文件的解决办法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

问题导读

1.本文的应用场景是什么?
2.Hive读取不到Flume正在写入的HDFS临时文件,该如何解决?

实际工作遇到如下场景:应用服务器收集到的日志信息,通过Flume写入到HDFS指定目录,而Hive将其映射到表,进行离线统计。

计划

计划方式处理:

Hive的表创建为外部分区表,例如:

  1. USE mydb;
  2. CREATE EXTERNAL TABLE mytable
  3.   c1 String,
  4.   c2 INT,
  5.   c3 INT,
  6.   create_time String
  7. )
  8. PARTITIONED BY (dt STRING);

然后创建分区,如:

ALTER TABLE mytable ADD PARTITION (dt = ’2013-09-25′) LOCATION ‘/data/mytable/2013-09-25/’;
ALTER TABLE mytable ADD PARTITION (dt = ’2013-09-26′) LOCATION ‘/data/mytable/2013-09-26/’;
ALTER TABLE mytable ADD PARTITION (dt = ’2013-09-27′) LOCATION ‘/data/mytable/2013-09-27/’;

即Hive的表按天进行分区。指定到相应目录。

而Flume中配置将数据保存到HDFS中,即HDFS sink。计划每天一个文件,进行日切。如2013-09-25对应的文件就保存在:

hdfs://<hive.metastore.warehouse.dir>/data/mytable/2013-09-25/FlumeData.xxx

 

这样,只要文件生成,就能直接通过操作Hive的mytable表来对文件进行统计了。

业务上要求统计工作是按照小时进行,考虑到按照小时进行分区过于细化,而且会导致过多的文件给NameNode造成内存压力,所以如上Hive层面按天进行划分。

统计执行时首先指定天分区,然后根据create_time(mm:hh:ss)指定统计时间段,如:

 

SELECT c1,
            SUM(c2),
            SUM(c3)
FROM mytable
WHERE dt = ’2013-09-25′
     AND create_time BETWEEN ’22:00:00′ AND ’22:59:59′
GROUP BY c1
;

 

但是,但是,计划始终赶不到遇到的变化!

在实践的过程中遇到如下两个问题:

1.对于正在写入的文件,通过hadoop fs -ls 命令查看,其大小始终是0,即使通过hadoop fs -cat可以看到实际已经有内容存在!通过hive处理的话也看不到其中的数据。

2.Flume正在写入的文件,默认会有.tmp后缀。如果Hive在执行过程中,Flume切换文件,即将xxx.tmp重命名为xxx,这时Hive会报错如file not found xxx.tmp。

了解一番后大致知道了缘由,记录如下:

针对问题1

首先了解HDFS的特点:

HDFS中所有文件都是由块BLOCK组成,默认块大小为64MB。在我们的测试中由于数据量小,始终在写入文件的第一个BLOCK。而HDFS与一般的POSIX要求的文件系统不太一样,其文件数据的可见性是这样的:

  • 如果创建了文件,这个文件可以立即可见;
  • 写入文件的数据则不被保证可见了,哪怕是执行了刷新操作(flush/sync)。只有数据量大于1个BLOCK时,第一个BLOCK的数据才会被看到,后续的BLOCK也同样的特性。正在写入的BLOCK始终不会被其他用户看到!
  • HDFS中的sync()保证数据持久化到了datanode上,然后可以被其他用户看到。

针对HDFS的特点,可以解释问题1中的现象,正在写入无法查看。但是使用Hive统计时Flume还在写入那个BLOCK(数据量小的时候),那岂不是统计不到信息?

解决方案:

每天再按小时切分文件——这样虽然每天文件较多,但是能够保证统计时数据可见!Flume上的配置项为hdfs.rollInterval。

如果文件数多,那么还可以考虑对以前的每天的小时文件合并为每天一个文件!


 

针对问题2

原因比较明显,Hive处理前获取了对应分区下的所有文件信息,其中包含xxx.tmp文件,而传递给MapReduce处理时,由于Flume进行了切换,导致原来的xxx.tmp变成了xxx,新的.tmp名称又变成了yyy.tmp,这样自然找不到xxx.tmp了。

解决方案:

解决这个问题想法之一是想控制Hive的处理时机,但是显然不是那么好控制。

进一步了解到HDFS的Java API读取HDFS文件时,会忽略以”.”和”_”开头的文件!类似于Linux中默认.xx是隐藏的一样,应用程序读取HDFS文件时默认也不读取.xxx和_xxx这样名称的文件!

这样就产生了针对问题2的处理方案一)配置Flume,针对正在写入的文件,以.号开头。涉及Flume配置项hdfs.inUsePrefix。

也有网友给出了处理方案二):让应用程序也看不到.tmp结尾的文件!方法是继承PathFilter自定义自己的文件筛选类,然后在Hive中设置使用这个类。具体如下(转自此文)

  1. package com.twitter.util;
  2.  
  3. import java.io.IOException;
  4. import java.util.ArrayList;
  5. import java.util.List;
  6. import org.apache.hadoop.fs.Path;
  7. import org.apache.hadoop.fs.PathFilter;
  8.  
  9. public class FileFilterExcludeTmpFiles implements PathFilter {
  10.     public boolean accept(Path p) {
  11.         String name = p.getName();
  12.         return !name.startsWith(“_”) && !name.startsWith(“.”) && !name.endsWith(“.tmp”);
  13.     }
  14. }

复制代码
 

然后在hive-site.xml中加入:

  1. <property>
  2.     <name>hive.aux.jars.path</name>
  3.     <value>file:///usr/lib/hadoop/hive-serdes-1.0-SNAPSHOT.jar,file:///usr/lib/hadoop/TwitterUtil.jar</value>
  4. </property>
  5. <property>
  6.     <name>mapred.input.pathFilter.class</name>
  7.     <value>com.twitter.util.FileFilterExcludeTmpFiles</value>
  8. </property>


 

Done!

 

 

这篇关于Hive读取不到Flume正在写入的HDFS临时文件的解决办法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1024684

相关文章

HDFS—存储优化(纠删码)

纠删码原理 HDFS 默认情况下,一个文件有3个副本,这样提高了数据的可靠性,但也带来了2倍的冗余开销。 Hadoop3.x 引入了纠删码,采用计算的方式,可以节省约50%左右的存储空间。 此种方式节约了空间,但是会增加 cpu 的计算。 纠删码策略是给具体一个路径设置。所有往此路径下存储的文件,都会执行此策略。 默认只开启对 RS-6-3-1024k

HDFS—集群扩容及缩容

白名单:表示在白名单的主机IP地址可以,用来存储数据。 配置白名单步骤如下: 1)在NameNode节点的/opt/module/hadoop-3.1.4/etc/hadoop目录下分别创建whitelist 和blacklist文件 (1)创建白名单 [lytfly@hadoop102 hadoop]$ vim whitelist 在whitelist中添加如下主机名称,假如集群正常工作的节

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0

matlab读取NC文件(含group)

matlab读取NC文件(含group): NC文件数据结构: 代码: % 打开 NetCDF 文件filename = 'your_file.nc'; % 替换为你的文件名% 使用 netcdf.open 函数打开文件ncid = netcdf.open(filename, 'NC_NOWRITE');% 查看文件中的组% 假设我们想读取名为 "group1" 的组groupName

Solr 使用Facet分组过程中与分词的矛盾解决办法

对于一般查询而言  ,  分词和存储都是必要的  .  比如  CPU  类型  ”Intel  酷睿  2  双核  P7570”,  拆分成  ”Intel”,”  酷睿  ”,”P7570”  这样一些关键字并分别索引  ,  可能提供更好的搜索体验  .  但是如果将  CPU  作为 Facet  字段  ,  最好不进行分词  .  这样就造成了矛盾  ,  解决方法

ORACLE 11g 创建数据库时 Enterprise Manager配置失败的解决办法 无法打开OEM的解决办法

在win7 64位系统下安装oracle11g,在使用Database configuration Assistant创建数据库时,在创建到85%的时候报错,错误如下: 解决办法: 在listener.ora中增加对BlueAeri-PC或ip地址的侦听,具体步骤如下: 1.启动Net Manager,在“监听程序”--Listener下添加一个地址,主机名写计

Anaconda 中遇到CondaHTTPError: HTTP 404 NOT FOUND for url的问题及解决办法

最近在跑一个开源项目遇到了以下问题,查了很多资料都大(抄)同(来)小(抄)异(去)的,解决不了根本问题,费了很大的劲终于得以解决,记录如下: 1、问题及过程: (myenv) D:\Workspace\python\XXXXX>conda install python=3.6.13 Solving environment: done.....Proceed ([y]/n)? yDownloa

[环境配置]ubuntu20.04安装后wifi有图标但是搜不到热点解决方法

最近刚入手一台主机,暗影精灵8plus电竞主机,安装ubuntu后wifi怎么都搜不到热点,前后重装系统6次才算解决问题。这个心酸历程只有搞技术人才明白。下面介绍我解决过程。 首先主机到手后是个windows10系统,我用无线网连接了一下,可以正常上网,说明主机有无限网卡且正常。然后我就直接开始安装Ubuntu20.04了,安装成功后发现wifi有图标但是搜不到热点,我想是不是无线网卡驱动有没有

如何保证android程序进程不到万不得已的情况下,不会被结束

最近,做一个调用系统自带相机的那么一个功能,遇到的坑,在此记录一下。 设备:红米note4 问题起因 因为自定义的相机,很难满足客户的所有需要,比如:自拍杆的支持,优化方面等等。这些方面自定义的相机都不比系统自带的好,因为有些系统都是商家定制的,难免会出现一个奇葩的问题。比如:你在这款手机上运行,无任何问题,然而你换一款手机后,问题就出现了。 比如:小米的红米系列,你启用系统自带拍照功能后

argodb自定义函数读取hdfs文件的注意点,避免FileSystem已关闭异常

一、问题描述 一位同学反馈,他写的argo存过中调用了一个自定义函数,函数会加载hdfs上的一个文件,但有些节点会报FileSystem closed异常,同时有时任务会成功,有时会失败。 二、问题分析 argodb的计算引擎是基于spark的定制化引擎,对于自定义函数的调用跟hive on spark的是一致的。udf要通过反射生成实例,然后迭代调用evaluate。通过代码分析,udf在