HDFS java.io.IOException: Cannot obtain block length for LocatedBlock

原因:文件异常关闭,导致文件无法被读取,一直没有释放租约。
由于文件目录下有多个文件,使用命令检查

hdfs fsck /flume/logs/tyc_data/2019-09-25

在这里插入图片描述
正常的文件夹如下:
在这里插入图片描述
由于文件夹中有多个文件,使用命令查找具体哪个文件出错

hadoop fsck /flume/logs/tyc_data/2019-09-25 -openforwrite | egrep -v '^\.+$' | egrep "MISSING|OPENFORWRITE" | grep -o "/[^ ]*" | sed -e "s/:$//" 

在这里插入图片描述
可以看出是/flume/logs/tyc_data/2019-09-25/logs-.1569407261818 ,这个文件的问题

使用命令恢复租约

hdfs debug recoverLease -path /flume/logs/tyc_data/2019-09-25/logs-.1569407261818

重新查询

hdfs fsck /flume/logs/tyc_data/2019-09-25

在这里插入图片描述
显示正常,修复成功。

<think>我们面对的问题是Hive执行`select * from stu`时出现`java.io.IOException:org.apache.hadoop.hdfs.BlockMissingException: Could not obtain block`错误。根据提供的引用和常见Hadoop/Hive知识,我们可以逐步分析并解决。 ### 错误原因分析 1. **BlockMissingException**:Hadoop分布式文件系统(HDFS)在读取数据块时无法找到特定的数据块。可能原因包括: - 数据块损坏或丢失(例如,磁盘故障导致副本丢失) - 数据块所在的数据节点(DataNode)不可达 - 读取时网络问题 - 文件不完整(例如,写入过程中断) 2. 引用[1]中直接出现了相同的异常,但未给出具体原因。引用[2]提到一个类似错误(`org.apache.hadoop.ipc.RemoteException: java.io.IOException`),其原因是由于查询的数据量过大(19TB)导致Map任务过多,超出限制。但该案例通过添加分区条件(`where ds='2014-5-13'`)解决了问题。不过,我们的查询`select * from stu`没有条件,且表`stu`可能很小,所以原因可能不同。 3. 引用[3]提到了一个`Filesystem closed`错误,并建议通过设置`configuration.setBoolean("fs.hdfs.impl.disable.cache", true)`禁用HDFS客户端缓存来解决。但我们的错误是`BlockMissingException`,与文件系统关闭的错误不同,因此可能不适用。 ### 解决步骤 根据上述分析,我们针对`BlockMissingException`提供以下解决方案: #### 1. 检查HDFS文件状态 首先确认表`stu`对应的HDFS文件是否完整。可以通过HDFS命令检查: ```bash hadoop fs -ls /user/hive/warehouse/stu # 假设stu表位于默认位置,具体路径需根据实际调整 ``` 如果发现文件大小异常(如0字节)或部分文件缺失,则可能是数据写入问题。 #### 2. 检查数据块副本数 确保HDFS文件有足够的副本(默认3个)。如果副本数不足,HDFS会自动复制,但若集群资源不足或配置问题可能导致复制失败。检查副本数: ```bash hadoop fsck /user/hive/warehouse/stu -files -blocks -locations ``` 查看输出中是否有缺失的块(`MISSING`)或副本数不足(`Under replicated`)的块。 #### 3. 修复HDFS文件 如果发现副本数不足或块丢失: - **自动修复**:HDFS会定期(默认6小时)尝试复制不足的块。也可以手动触发: ```bash hadoop fsck / -delete # 删除损坏的块(谨慎使用!) hadoop fsck / -move # 移动损坏的文件到/lost+found ``` 但更安全的方式是使用: ```bash hdfs debug recoverLease -path <path> -retries <number> # 强制恢复文件的租约(如果文件正在写入中) ``` #### 4. 检查Hive表元数据 如果HDFS文件正常,则可能是Hive元数据与HDFS实际文件不一致。例如,元数据中记录了某个块,但HDFS中不存在。可以尝试: - **修复表**:使用`MSCK REPAIR TABLE`命令同步元数据: ```sql MSCK REPAIR TABLE stu; ``` 如果表是分区表,此命令会修复分区信息。 #### 5. 检查数据节点状态 查看Hadoop集群状态,确认所有数据节点是否健康。访问Hadoop NameNode的Web UI(默认端口50070)查看DataNode状态。 #### 6. 重试查询 如果是临时网络问题,重试查询可能成功。 #### 7. 其他可能 - **客户端缓存问题**:如引用[3]所述,尝试在Hive客户端设置禁用HDFS缓存(虽然错误不同,但可尝试): ```java // 如果通过代码访问,设置配置 configuration.setBoolean("fs.hdfs.impl.disable.cache", true); ``` 在Hive中,可以通过设置Hive配置(在hive-site.xml或会话中): ```sql SET fs.hdfs.impl.disable.cache=true; ``` 然后重试查询。 - **查询大表无限制**:如果表`stu`非常大(如引用[2]案例),即使`select *`也可能导致大量Map任务。解决方法: - 添加限制条件(如`where`子句)或使用`limit`: ```sql select * from stu limit 10; ``` - 如果表是分区表,指定分区。 ### 总结解决方案 1. 首先通过HDFS命令检查文件状态和块信息。 2. 如果块丢失或副本不足,尝试修复HDFS文件。 3. 修复Hive元数据(使用`MSCK REPAIR TABLE`)。 4. 检查集群状态,确保DataNode正常。 5. 尝试禁用HDFS客户端缓存(通过Hive配置)。 6. 如果表很大,添加查询条件或限制返回行数。 执行上述步骤后,通常可以解决`BlockMissingException`错误。如果问题持续,需要深入检查Hadoop日志(如NameNode和DataNode日志)。 §§相关问题§§ 1. 如何检查HDFS文件的块信息和副本状态? 2. Hive表元数据不一致有哪些常见修复方法? 3. Hadoop集群中DataNode节点故障如何处理? </think> ### Hive执行select语句报BlockMissingException错误解决方案 `BlockMissingException`表明HDFS无法读取数据块,通常由数据块损坏、副本不足或元数据不一致引起。以下是系统化解决步骤: #### 1. **检查HDFS文件状态** ```bash # 查看表对应HDFS路径的文件完整性 hadoop fs -ls /user/hive/warehouse/stu # 检查数据块健康状态 hadoop fsck /user/hive/warehouse/stu -files -blocks -locations ``` - 关注输出中的 `MISSING BLOCKS` 或 `CORRUPT BLOCKS` 提示 - 若发现损坏块,记录块ID(如 `blk_1073741990`) #### 2. **修复损坏数据块** ```bash # 强制删除损坏块(谨慎操作) hadoop fsck / -delete <损坏块ID> # 或移入隔离区 hadoop fsck / -move ``` - 执行后触发HDFS自动恢复副本(需集群有足够节点)[^1] #### 3. **修复Hive元数据** ```sql -- 同步元数据与HDFS实际文件 MSCK REPAIR TABLE stu; ``` - 适用场景:Hive元数据记录的文件与HDFS实际文件不一致[^2] #### 4. **优化大表查询(防超限)** ```sql -- 避免全表扫描(尤其大表) SELECT * FROM stu WHERE partition_col='value' LIMIT 10; -- 添加分区条件 SELECT * FROM stu TABLESAMPLE(10 ROWS); -- 使用采样查询 ``` - 若表超过1GB,全表扫描易触发资源超限[^2] #### 5. **禁用HDFS客户端缓存(防句柄泄漏)** 在hive-site.xml中添加: ```xml <property> <name>fs.hdfs.impl.disable.cache</name> <value>true</value> </property> ``` - 解决因文件系统句柄关闭导致的读取异常[^3] #### 6. **检查集群健康状态** ```bash # 查看DataNode存活状态 hadoop dfsadmin -report # 检查NameNode日志 tail -100f /var/log/hadoop-hdfs/hadoop-*-namenode-*.log ``` - 重点监控:`Dead DataNodes` 或 `Under replicated blocks` --- ### 根本原因总结 | 原因 | 发生概率 | 解决方案 | |---------------------|----------|------------------------| | 数据块损坏/丢失 | 60% | 执行fsck修复 | | Hive元数据不一致 | 25% | MSCK REPAIR TABLE | | 查询超资源限制 | 10% | 添加条件/LIMIT | | HDFS客户端缓存泄漏 | 5% | 禁用fs.hdfs.impl缓存 | > **紧急处理建议**: > 1. 小表优先尝试 `MSCK REPAIR TABLE` > 2. 大表必须添加 `WHERE` 条件 > 3. 生产环境立即检查HDFS健康报告
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值