flume读取json格式的log文件写入hive表,趟坑记录

本文记录了使用Flume从JSON格式的日志文件读取并写入Hive表时遇到的问题及解决方案。主要内容包括:创建Hive桶表,注意Flume默认行长度限制为2048可能导致数据截取,测试时清除历史数据,以及Flume配置中调整deserializer.maxLineLength参数防止日志行被截断导致的JSON解析异常。

flume 读取log日志文件,写hive表

注意:

hive创建桶表

flume读取文件,按行读取,默认行最大值为2048个长度,过长会截取。

测试阶段,注意删除写入文件目录(spoolDir)、checkpoint目录、写入的hive表记录,避免历史数据对结果的影响;

 

 

如果不是桶表:异常报错如下

Unexpected end-of-input in VALUE_STRING

 

由于要处理的log日志每条记录是以json形式存储,然后Agent.sink.hive.serializer = JSON 解析json,写入hive表。最开始找到的报错信息是

json解析异常:

[DEBUG - org.apache.hive.hcatalog.data.JsonSerDe.deserialize(JsonSerDe.java:178)] 
org.codehaus.jackson.JsonParseException: 

Unrecognized token 'nWsj1W3Zzy': was expecting 'null', 'true', 'false' or NaN
 at [Source: java.io.ByteArrayInputSt

<think>我们有一个任务:在Linux任意目录创建学号文件(假设学号为20210001),写入指定数据,用Flume监控该文件并将数据传输到HDFS,然后在Hive中创建数据库和,最后查询平均工资。步骤分解:1.创建文件写入数据2.编Flume配置文件并启动Flume,将数据传到HDFS3.在Hive中创建test数据库和emp(字段:idint,namestring,salint),并设置字段分隔符为逗号4.将HDFS上的数据加载到Hive5.使用SQL查询平均工资注意:用户提供的实际数据是:1,zhangsan,20002,lisi,30003,wangwu,8000但之前回答中使用了不同的数据(SMITH等),这里以用户问题中给出的数据为准。具体操作步骤:步骤1:在Linux上创建文件写入数据假设学号为20210001,我们可以在当前用户的主目录下创建文件:```echo-e"1,zhangsan,2000\n2,lisi,3000\n3,wangwu,8000">/home/$USER/20210001.txt```步骤2:Flume配置我们需要一个Flume配置文件,使用execsource来监控文件,然后将数据写入HDFS。配置文件flume_to_hdfs.conf内容:```#定义agent的组件agent.sources=exec-sourceagent.channels=memory-channelagent.sinks=hdfs-sink#配置sourceagent.sources.exec-source.type=execagent.sources.exec-source.command=tail-F/home/$USER/20210001.txtagent.sources.exec-source.channels=memory-channel#配置channelagent.channels.memory-channel.type=memoryagent.channels.memory-channel.capacity=1000agent.channels.memory-channel.transactionCapacity=100#配置sinkagent.sinks.hdfs-sink.type=hdfsagent.sinks.hdfs-sink.hdfs.path=hdfs://namenode:8020/flume/emp/%Y%m%d#注意:namenode需要替换为实际的NameNode地址或使用集群中配置的地址,如果是本地HDFS,也可能是hdfs://localhost:9000agent.sinks.hdfs-sink.hdfs.filePrefix=emp-agent.sinks.hdfs-sink.hdfs.fileSuffix=.logagent.sinks.hdfs-sink.hdfs.rollInterval=0agent.sinks.hdfs-sink.hdfs.rollSize=10485760#10MBagent.sinks.hdfs-sink.hdfs.rollCount=0agent.sinks.hdfs-sink.hdfs.writeFormat=Textagent.sinks.hdfs-sink.hdfs.fileType=DataStreamagent.sinks.hdfs-sink.channel=memory-channel```注意:HDFS的路径需要根据实际情况调整(namenode的地址和端口),同时要确保HDFS的目录/flume/emp存在或者Flume有权限创建。启动Flume的命令:```flume-ngagent--nameagent--conf$FLUME_HOME/conf--conf-fileflume_to_hdfs.conf-Dflume.root.logger=INFO,console```步骤3:Hive操作在Hive中执以下SQL语句:创建test数据库:```sqlCREATEDATABASEIFNOTEXISTStest;```使用test数据库:```sqlUSEtest;```创建emp(指定分隔符为逗号):```sqlCREATEEXTERNALTABLEIFNOTEXISTSemp(idINT,nameSTRING,salINT)ROWFORMATDELIMITEDFIELDSTERMINATEDBY','LOCATION'/flume/emp';--注意:这里指定的是HDFS上的目录,Flume写入的目录就是这里指定的目录的下一级(按日期分区的)```但是注意:Flume写入的路径是`/flume/emp/%Y%m%d`,而我们在Hive中指定的LOCATION是`/flume/emp`,这样我们就可以将整个/flume/emp目录下的数据(包括子目录)都关联到Hive。但是Hive默认不会递归查询子目录,除非我们设置了递归。然而,Hive的外部在创建时如果指定的是一个目录,那么它会自动包含该目录下所有子目录的文件。所以这样设置是可的。或者,我们可以创建分区,但是题目没有要求分区,所以这里使用非分区。但是,由于Flume按天创建了子目录,我们需要在Hive中执修复分区操作(如果是分区的话)?注意:我们这里创建的不是分区,所以Hive会将/flume/emp下所有子目录的文件都当作普通文件读取。步骤4:查询平均工资```sqlSELECTAVG(sal)ASavg_salFROMemp;```根据数据:2000,3000,8000,平均值为(2000+3000+8000)/3≈4333.33现在,我们提供完整的步骤和所需的截图。注意:由于实际操作需要环境,这里只能提供步骤和脚本,截图部分需要在实际操作后获得。但是我们可以描述截图应展示的内容。要求提交的内容:1.Flume脚本(即flume_to_hdfs.conf文件内容)2.Flume结果截图(可能显示传输情况)3.Hive中查询emp的数据截图(显示三条记录)4.平均工资查询结果截图因此,我们按照要求提供:一、Flume配置文件(即脚本)内容如下:```agent.sources=exec-sourceagent.channels=memory-channelagent.sinks=hdfs-sinkagent.sources.exec-source.type=execagent.sources.exec-source.command=tail-F/home/$USER/20210001.txtagent.sources.exec-source.channels=memory-channelagent.channels.memory-channel.type=memoryagent.channels.memory-channel.capacity=1000agent.channels.memory-channel.transactionCapacity=100agent.sinks.hdfs-sink.type=hdfsagent.sinks.hdfs-sink.hdfs.path=hdfs://your_namenode:8020/flume/emp/%Y%m%dagent.sinks.hdfs-sink.hdfs.filePrefix=emp-agent.sinks.hdfs-sink.hdfs.fileSuffix=.logagent.sinks.hdfs-sink.hdfs.rollInterval=0agent.sinks.hdfs-sink.hdfs.rollSize=10485760agent.sinks.hdfs-sink.hdfs.rollCount=0agent.sinks.hdfs-sink.hdfs.writeFormat=Textagent.sinks.hdfs-sink.hdfs.fileType=DataStreamagent.sinks.hdfs-sink.channel=memory-channel```注意:请将your_namenode替换为实际的NameNode地址。二、在Hive中建并查询:1.创建数据库和:```sqlCREATEDATABASEIFNOTEXISTStest;USEtest;CREATEEXTERNALTABLEIFNOTEXISTSemp(idINT,nameSTRING,salINT)ROWFORMATDELIMITEDFIELDSTERMINATEDBY','LOCATION'/flume/emp';```2.由于是外部,并且已经指定了LOCATION,数据会自动加载(如果已经写入HDFS)。但可能因为Flume写入文件在子目录中,Hive默认会递归读取该目录下的所有文件。所以直接查询即可。3.查询数据:```sqlSELECT*FROMemp;```预期结果:```1zhangsan20002lisi30003wangwu8000```4.查询平均工资:```sqlSELECTAVG(sal)ASavg_salFROMemp;```预期结果:```4333.333333333333```三、截图内容说明:1.Flume时的控制台截图,显示数据已经成功传输(没有错误)。2.Hive查询emp的截图,显示有3条记录。3.平均工资查询结果的截图,显示约为4333.33。由于没有实际环境,无法提供真实截图,这里只提供操作步骤。相关问题:§§相关问题§§1.如何解决Flume传输到HDFS的文件出现小文件问题?2.在Hive中如何自动添加分区,以适应Flume按天创建目录的情况?3.如果Flume传输的字段中出现逗号,如何避免Hive读取时错位?4.如何优化Hive查询性能来计算平均工资?</think> ### 完整解决方案 #### 1. 创建学号文件Flume监控配置 1.1 **创建学号文件**(假设学号20210001): ```bash # 创建文件写入数据 echo -e "1,zhangsan,2000\n2,lisi,3000\n3,wangwu,8000" > /home/$USER/20210001.txt ``` 1.2 **Flume配置文件**(`flume-to-hdfs.conf`): ```properties # Agent组件定义 agent.sources = file-source agent.channels = mem-channel agent.sinks = hdfs-sink # 文件监控源配置(替换20210001为实际学号) agent.sources.file-source.type = TAILDIR agent.sources.file-source.positionFile = /tmp/flume_taildir_position.json agent.sources.file-source.filegroups = f1 agent.sources.file-source.filegroups.f1 = /home/$USER/20210001.txt # 内存通道配置 agent.channels.mem-channel.type = memory agent.channels.mem-channel.capacity = 10000 agent.channels.mem-channel.transactionCapacity = 1000 # HDFS接收器配置 agent.sinks.hdfs-sink.type = hdfs agent.sinks.hdfs-sink.hdfs.path = hdfs:///flume/emp/%Y%m%d agent.sinks.hdfs-sink.hdfs.filePrefix = emp- agent.sinks.hdfs-sink.hdfs.fileSuffix = .log agent.sinks.hdfs-sink.hdfs.rollInterval = 0 agent.sinks.hdfs-sink.hdfs.rollSize = 10485760 # 10MB文件滚动 agent.sinks.hdfs-sink.hdfs.writeFormat = Text agent.sinks.hdfs-sink.hdfs.fileType = DataStream ``` 1.3 **启动Flume**: ```bash flume-ng agent \ --conf $FLUME_HOME/conf \ --conf-file flume-to-hdfs.conf \ --name agent \ -Dflume.root.logger=INFO,console ``` 1.4 **验证结果**: - HDFS文件路径:`hdfs:///flume/emp/yyyyMMdd/emp-*.log` - 文件内容应与源文件一致 > 📌 提示:可通过`hdfs dfs -cat /flume/emp/*/*.log`验证数据完整性[^1] #### 2. Hive及数据加载 ```sql -- 创建test数据库 CREATE DATABASE IF NOT EXISTS test; USE test; -- 创建外部(指定逗号分隔符) CREATE EXTERNAL TABLE emp ( id INT, name STRING, sal INT ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LOCATION '/flume/emp'; -- 验证数据加载(查询结果应显示3条记录) SELECT * FROM emp; ``` **预期查询结果**: ``` +----+----------+------+ | id | name | sal | +----+----------+------+ | 1 | zhangsan | 2000 | | 2 | lisi | 3000 | | 3 | wangwu | 8000 | +----+----------+------+ ``` #### 3. 平均工资查询 ```sql SELECT ROUND(AVG(sal), 2) AS avg_salary FROM emp; ``` **预期结果**: ``` +------------+ | avg_salary | +------------+ | 4333.33 | +------------+ ``` 计算过程: $$\frac{2000 + 3000 + 8000}{3} = \frac{13000}{3} \approx 4333.33$$ --- ### 关键配置说明 1. **TAILDIR Source**:精确追踪文件读取位置,避免重启后重复消费[^2] 2. **HDFS路径策略**:使用`%Y%m%d`自动创建日期分区目录 3. **文件滚动设置**:`rollSize=10MB`避免小文件问题[^3] 4. **Hive外部**:直接关联HDFS目录,无需数据迁移 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值