在HBase上跑MapReduce有个很麻烦的问题:多HTable+多Scan作为Map的Input对象。以往都需要开发人员去写TableInputFormat类的重载方法。
HBase 0.94.6版本加入了一个新的Class::MultiTableInputFormatBase。(这里我提醒一下HBase 0.94.6有致命BUG,请用0.94.7)
这个方法可以帮助MapReduce开发人员快速实现多HTable+多Scan的Input。
MultiTableInputFormatBase的实现源于HBASE-3996:Support multiple tables and scanners as input to the mapper in map/reduce jobs
MultiTableInputFormatBase的加入的同时,补丁还调整了TableMapReduceUtil,并加入了以下方法:
//多输入方法
void org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil.initTableMapperJob(
List<Scan> scans,
Class<? extends TableMapper> mapper,
Class<? extends WritableComparable> outputKeyClass,
Class<? extends Writable> outputValueClass, Job job
) throws IOException
//单输入方法
void org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil.initTableMapperJob(
String table,
Scan scan, Class<? extends TableMapper> mapper,
Class<? extends WritableComparable> outputKeyClass,
Class<? extends Writable> outputValueClass, Job job
) throws IOException
多输入方法相比单输入方法的最大区别在于:去掉了Table Name的传入参数,取而代之的是一个List<Scan>
现在问题来了,新方法只有Scan,没有HTable名称。如何让MapReduce知道数据从哪几张表获取呢?
经过几番周折,我在MultiTableInputFormatBase.java源码的第116行找到了答案
byte[] tableName = scan.getAttribute(Scan.SCAN_ATTRIBUTES_TABLE_NAME);
if (tableName ==