我正在使用
Hbase:0.92.1-cdh4.1.2,和Hadoop:2.0.0-cdh4.1.2
我有一个mapreduce程序,它将在集群模式下使用HFileOutputFormat将数据从HDFS加载到HBase。在那个mapreduce程序中,我使用HFileOutputFormat.configureIncrementalLoad()来大容量加载800000条记录7.3GB大小的数据集,运行良好,但不适用于8.3GB的900000记录数据集。
在8.3GB数据的情况下,我的mapreduce程序有133个地图和一个reducer,所有地图都成功完成。我的reducer状态长期处于挂起状态。集群没有任何问题,因为其他作业运行良好,而此作业也运行良好,数据量高达7.3GB。
我可能做错了什么?如何解决此问题?
我遇到了同样的问题。查看DataTracker日志,我注意到没有足够的可用空间让单个reducer在我的任何节点上运行:
2013-09-15 16:55:19,385 WARN org.apache.hadoop.mapred.JobInProgress: No room for reduce task. Node tracker_slave01.mydomain.com:localhost/127.0.0.1:43455 has 503,777,017,856 bytes free; but we expect reduce input to take 978136413988
这个503gb指的是特定从机("tracker_slave01.mydomain.com")上的一个硬盘驱动器上的可用空间,因此reducer显然需要将所有数据复制到一个驱动器上。
发生这种情况的原因是,当你的桌子是全新的时,它只有一个区域。当数据插入该区域时,它最终会自行拆分。
解决方案是在创建表时预先创建区域。HBase书中的散装装载章节对此进行了讨论,并提供了两种选择。这也可以通过HBaseshell来完成(我想请参阅create
的SPLITS
参数)。然而,挑战在于定义分割,以便区域获得均匀的密钥分布。我还没有完全解决这个问题,但我目前正在做的是:
HTableDescriptor desc = new HTableDescriptor();
desc.setName(Bytes.toBytes(tableName));
desc.addFamily(new HColumnDescriptor("my_col_fam"));
admin.createTable(desc, Bytes.toBytes(0), Bytes.toBytes(2147483647), 100);
另一种解决方案是不使用configureIncrementalLoad
,而是:1)只通过MapReduce生成HFile,不使用reducers;2) 使用hbase.jar中的completebulkload
功能将您的记录导入hbase。当然,我认为区域也会遇到同样的问题,所以你也需要提前创建区域(我认为)。
您的作业运行时带有单个reduce,这意味着在单个任务中处理7GB的数据。主要原因是HFileOutputFormat启动了reducer,对要加载到HBase表中的数据进行排序和合并。这里,Num of Reducer=HBase表中的区域数
增加区域的数量,您将在减速器中实现并行。:)
您可以在此处获取更多详细信息:http://databuzzprd.blogspot.in/2013/11/bulk-load-data-in-hbase-table.html