一.错误
使用BulkLoad向Hbase导入数据时出现了错误
2014-04-04 15:39:08,521 WARN org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles - Bulk load operation did not find any files to load in directory hdfs://192.168.1.200:9000/user/root/output1. Does it contain files in subdirectories that correspond to column family names?
然后去看MapReduce的临时输出目录,果然没有data文件夹,只有_SUCCESS文件。
二.job.setMapOutputValueClass与job.setOutputValueClass
这一定是Reduce的问题了,去看看HFileOutputFormat.configureIncrementalLoad(job, htable); 到底做了什么。
job.setOutputKeyClass(ImmutableBytesWritable.class); job.setOutputValueClass(KeyValue.class); job.setOutputFormatClass(HFileOutputFormat.class); // Based on the configured map output class, set the correct reducer to properly // sort the incoming values. // TODO it would be nice to pick one or the other of these formats. if (KeyValue.class.equals(job.getMapOutputValueClass())) { job.setReducerClass(KeyValueSortReducer.class); } else if (Put.class.equals(job.getMapOutputValueClass())) { job.setReducerClass(PutSortReducer.class); } else if (Text.class.equals(job.getMapOutputValueClass())) { job.setReducerClass(TextSortReducer.class); } else { LOG.warn("Unknown map output value type:" + job.getMapOutputValueClass()); }
Debug时发现,job.getMapOutputValueClass为KeyValue。再看看job.setMapOutputValueClass和job.setOutputValueClass的区别
getOutputValueClass mapreduce.job.output.value.class setOutputValueClass mapreduce.job.output.value.class setMapOutputValueClass mapreduce.map.output.value.class getMapOutputValueClass mapreduce.map.output.value.class /** * Set the value class for the map output data. This allows the user to * specify the map output value class to be different than the final output * value class. * * @param theClass the map output value class. * @throws IllegalStateException if the job is submitted */ public void setMapOutputValueClass(Class<?> theClass ) throws IllegalStateException { ensureState(JobState.DEFINE); conf.setMapOutputValueClass(theClass); } /** * Get the value class for the map output data. If it is not set, use the * (final) output value class This allows the map output value class to be * different than the final output value class. * * @return the map output value class. */ public Class<?> getMapOutputValueClass() { Class<?> retv = getClass(JobContext.MAP_OUTPUT_VALUE_CLASS, null, Object.class); if (retv == null) { retv = getOutputValueClass(); } return retv; }
也就是
- getMapOutputValueClass的值,在没有setMapOutputValueClass时,将使用setOutputValueClass的值。
- 允许map output value的class(即getMapOutputValueClass)和最终output value的(Reduceo output value的)class(即getOutputValueClass)不同。泛型类PutSortReducer<ImmutableBytesWritable, Put, ImmutableBytesWritable, KeyValue>说明map output value的class为Put,最终的为KeyValue。
- 上述同样适用于KeyClass。
我在程序里job.setOutputValueClass(Put.class),改为job.setMapOutputValueClass(Put.class)即可。
三.HBase删除所有数据
这个问题跟主题没有任何关系,就当做绿叶吧。
昨天突然有一想法,如果不重装Hbase,有没有办法“格式化”HBase。
首先想到的是删掉了Hdfs上hbase目录,再重启HBase,发现RegionServer连接不上Master。应该是-ROOT-表和.META.表已经被删掉了,RegionServer向zookeeper汇报心跳时,zookeeper去-ROOT-表里查找此RegionServer的相关信息,发现信息已经丢失,也就无法将此RegionServer信息通知给Master。删掉zookeeper信息,再次重启成功。
rm -rf /tmp/hbase-root*
<property> <name>hbase.zookeeper.property.dataDir</name> <value>/tmp/hbase-root</value> default <description>Property from ZooKeeper's config zoo.cfg. The directory where the snapshot is stored. </description> </property>