hey*_*you 5 hadoop hive hdfs cloudera hadoop-yarn
不久前我问了一个类似的问题,并以为我解决了这个问题,但结果它消失了,因为我正在处理一个较小的数据集。
许多人问过这个问题,我浏览了我能找到的每一个互联网帖子,但仍然没有取得任何进展。
我想要做的是:我browserdata
在 hive 中有一个外部表,它指的是大约 1 GB 的数据。我尝试将该数据粘贴到分区表中partbrowserdata
,其定义如下:
CREATE EXTERNAL TABLE IF NOT EXISTS partbrowserdata (
BidID string,
Timestamp_ string,
iPinYouID string,
UserAgent string,
IP string,
RegionID int,
AdExchange int,
Domain string,
URL string,
AnonymousURL string,
AdSlotID string,
AdSlotWidth int,
AdSlotHeight int,
AdSlotVisibility string,
AdSlotFormat string,
AdSlotFloorPrice decimal,
CreativeID string,
BiddingPrice decimal,
AdvertiserID string,
UserProfileIDs array<string>
)
PARTITIONED BY (CityID int)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
STORED AS TEXTFILE
LOCATION '/user/maria_dev/data2';
Run Code Online (Sandbox Code Playgroud)
使用此查询:
insert into table partbrowserdata partition(cityid)
select BidID,Timestamp_ ,iPinYouID ,UserAgent ,IP ,RegionID ,AdExchange ,Domain ,URL ,AnonymousURL ,AdSlotID ,AdSlotWidth ,AdSlotHeight ,AdSlotVisibility ,AdSlotFormat ,AdSlotFloorPrice ,CreativeID ,BiddingPrice ,AdvertiserID ,UserProfileIDs ,CityID
from browserdata;
Run Code Online (Sandbox Code Playgroud)
每次,在每个平台上,无论是 hortonworks 还是 cloudera,我都会收到以下消息:
Caused by:
org.apache.hadoop.ipc.RemoteException(java.io.IOException): File /user/maria_dev/data2/.hive-staging_hive_2019-02-06_18-58-39_333_7627883726303986643-1/_task_tmp.-ext-10000/cityid=219/_tmp.000000_3 could only be replicated to 0 nodes instead of minReplication (=1). There are 4 datanode(s) running and no node(s) are excluded in this operation.
at org.apache.hadoop.hdfs.server.blockmanagement.BlockManager.chooseTarget4NewBlock(BlockManager.java:1720)
at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.getAdditionalBlock(FSNamesystem.java:3389)
at org.apache.hadoop.hdfs.server.namenode.NameNodeRpcServer.addBlock(NameNodeRpcServer.java:683)
at org.apache.hadoop.hdfs.server.namenode.AuthorizationProviderProxyClientProtocol.addBlock(AuthorizationProviderProxyClientProtocol.java:214)
at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolServerSideTranslatorPB.addBlock(ClientNamenodeProtocolServerSideTranslatorPB.java:495)
at org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos$ClientNamenodeProtocol$2.callBlockingMethod(ClientNamenodeProtocolProtos.java)
at org.apache.hadoop.ipc.ProtobufRpcEngine$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine.java:617)
at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:1073)
at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2217)
at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2213)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:422)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1917)
at org.apache.hadoop.ipc.Server$Handler.run(Server.java:2211)
at org.apache.hadoop.ipc.Client.call(Client.java:1504)
at org.apache.hadoop.ipc.Client.call(Client.java:1441)
at org.apache.hadoop.ipc.ProtobufRpcEngine$Invoker.invoke(ProtobufRpcEngine.java:230)
at com.sun.proxy.$Proxy14.addBlock(Unknown Source)
at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolTranslatorPB.addBlock(ClientNamenodeProtocolTranslatorPB.java:413)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.hadoop.io.retry.RetryInvocationHandler.invokeMethod(RetryInvocationHandler.java:258)
at org.apache.hadoop.io.retry.RetryInvocationHandler.invoke(RetryInvocationHandler.java:104)
at com.sun.proxy.$Proxy15.addBlock(Unknown Source)
at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.locateFollowingBlock(DFSOutputStream.java:1814)
at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.nextBlockOutputStream(DFSOutputStream.java:1610)
at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.run(DFSOutputStream.java:773)
Run Code Online (Sandbox Code Playgroud)
我该怎么办?我不明白为什么会这样。不过,这似乎确实是一个内存问题,因为我可以插入几行,但由于某种原因不能插入所有行。请注意,我在 HDFS 上有足够的内存,所以 1 gig 的额外数据是一美元的便士,所以这可能是 RAM 问题?
这是我的 dfs 报告输出:
我已经在所有执行引擎上尝试过这个:spark
, tez
, mr
.
请不要建议说我需要格式化 namenode 的解决方案,因为它们不起作用,而且它们无论如何都不是解决方案。
更新:
查看 namenode 的日志后,我注意到了这一点,如果有帮助的话:
Failed to place enough replicas, still in need of 1 to reach 1 (unavailableStorages=[DISK ], storagePolicy=BlockStoragePolicy{HOT:7, storageTypes=[DISK], creationFallbacks=[], replicationFallbacks=[ARCHIVE]}, newBlock=true) All required storage types are unavailable: unavailableStorages=[DISK], stor agePolicy=BlockStoragePolicy{HOT:7, storageTypes=[DISK], creationFallbacks=[], replicationFallbacks=[ARCHIVE]}
Run Code Online (Sandbox Code Playgroud)
这些日志表明:
有关更多信息,请在 org.apache.hadoop.hdfs.ser ver.blockmanagement.BlockPlacementPolicy 和 org.apache.hadoop.net.NetworkTopology 上启用 DEBUG 日志级别
我怎么做?
我还注意到这里有一个类似的未解决的帖子:
HDP 2.2@Linux/CentOS@OracleVM (Hortonworks) 从 Eclipse@Windows 远程提交失败
更新2:
我只是尝试用 spark 进行分区,它有效!所以,这一定是一个蜂巢错误......
更新3:
刚刚在 MapR 上测试了它并且它有效,但 MapR 不使用 HDFS。这绝对是某种 HDFS + Hive 组合错误。
证明:
我最终联系了 cloudera 论坛,他们在几分钟内回答了我的问题:http : //community.cloudera.com/t5/Storage-Random-Access-HDFS/Why-can-tI-partition-a-1 -gigabyte-dataset-into-300/mp/86554#M3981我尝试了 Harsh J 的建议,效果很好!
他是这样说的:
如果您正在处理来自数据源的无序分区,则在尝试进行分区时,您最终可能会并行创建大量文件。
在 HDFS 中,当一个文件(或更具体地说,它的块)打开时,DataNode 执行其目标块大小的逻辑保留。因此,如果您配置的块大小为 128 MiB,那么每个并发打开的块都将从 DataNode 发布到 NameNode 的可用剩余空间中(逻辑上)扣除该值。
这样做是为了帮助管理空间并保证对客户端的完整块写入,以便开始写入其文件的客户端永远不会在中途遇到空间不足的异常。
注意:当文件关闭时,仅保留实际长度,并调整预留计算以反映已用和可用空间的实际情况。然而,当文件块保持打开状态时,它总是被认为拥有完整的块大小。
如果 NameNode 可以保证完整的目标块大小,则它只会选择一个 DataNode 进行写入。它将忽略它认为(基于其报告的值和指标)不适合所请求写入参数的任何 DataNode。您的错误表明 NameNode 在尝试分配新的块请求时已停止考虑您唯一的活动 DataNode。
例如,如果有 560 个以上的并发打开文件(70 GiB 分为 128 MiB 块大小),则 70 GiB 的可用空间将证明是不够的。因此,DataNode 将在大约 560 个打开文件时“显示已满”,并且不再作为进一步文件请求的有效目标。
根据您对插入的描述,这似乎是可能的,因为数据集的 300 个块中的每一个可能仍带有不同的 ID,导致每个并行任务请求大量打开文件,以插入到几个不同的分区中。
您可以通过减少查询中的请求块大小来“破解”这个问题(例如,将 dfs.blocksize 设置为 8 MiB),从而影响预留计算。但是,随着您的扩展,这对于较大的数据集可能不是一个好主意,因为它会增加文件:块计数并增加 NameNode 的内存成本。
解决此问题的更好方法是执行预分区插入(首先按分区排序,然后以分区方式插入)。例如,Hive 提供了一个选项: hive.optimize.sort.dynamic.partition,如果您使用普通的 Spark 或 MapReduce,那么它们的默认分区策略就是这样做的。
所以,在一天结束时,我做到了set hive.optimize.sort.dynamic.partition=true;
,一切都开始了。但我也做了另一件事。
这是我之前在调查此问题时发表的一篇文章:为什么在写入分区表时会收到“文件只能复制到 0 个节点”?我遇到了一个问题,hive 无法对我的数据集进行分区,因为hive.exec.max.dynamic.partitions
设置为100
,所以,我用谷歌搜索了这个问题,在 hortonworks 论坛的某个地方我看到了一个答案,说我应该这样做:
SET hive.exec.max.dynamic.partitions=100000;
SET hive.exec.max.dynamic.partitions.pernode=100000;
Run Code Online (Sandbox Code Playgroud)
这是另一个问题,也许 hive 尝试打开与您设置的一样多的并发连接hive.exec.max.dynamic.partitions
,因此insert
直到我将这些值减少到500
.