Hadoop生成HFile直接入库HBase心得

转载请标明出处:http://blackwing.iteye.com/blog/1991380 


hbase自带了ImportTsv类,可以直接把tsv格式(官方教材显示,是\t分割各个字段的文本格式)生成HFile,并且使用另外一个类org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles直接把HFile移动到hbase对应的hdfs目录。 

PS:网上看到一个XD说,直接生成HFile并入库HBase效率不如先生成HFile,再通过LoadIncrementalHFiles移动文件到hbase目录高,这点没有验证,我的做法也是先生成,再move。 

官方教材在此: 
Java代码   收藏代码
  1. http://hbase.apache.org/book/ops_mgt.html#importtsv  

但ImportTsv功能对我来说不适合,例如文件格式为: 
Java代码   收藏代码
  1. topsid   uid   roler_num   typ        time  
  2. 10      111111   255         0       1386553377000  

ImportTsv导入的命令为: 
Java代码   收藏代码
  1. bin/hbase org.apache.hadoop.hbase.mapreduce.ImportTsv -Dimporttsv.columns=HBASE_ROW_KEY,kq:topsid,kq:uid,kq:roler_num,kq:type -Dimporttsv.bulk.output=hdfs://storefile-outputdir   


它生成的表格式为: 
Java代码   收藏代码
  1. row : 10   
  2. cf  :  kq  
  3. qualifier: topsid  
  4. value: 10  
  5. .....  

而我要求的格式是: 
Java代码   收藏代码
  1. row : 10-111111-255  
  2. cf  :  kq  
  3. qualifier: 0  
  4. value: 1  


所以还是自己写MR处理数据方便。 
Mapper: 
Java代码   收藏代码
  1. /* 
  2.  * adminOnOff.log 文件格式: 
  3.  * topsid   uid   roler_num   typ   time 
  4.  * */  
  5. public class HFileImportMapper2 extends  
  6.         Mapper {  
  7.     protected SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");  
  8.     protected final String CF_KQ="kq";//考勤  
  9.     protected final int ONE=1;  
  10.     @Override  
  11.     protected void map(LongWritable key, Text value,Context context)  
  12.             throws IOException, InterruptedException {  
  13.         String line = value.toString();  
  14.         System.out.println("line : "+line);  
  15.         String[] datas = line.split("\\s+");  
  16.         // row格式为:yyyyMMdd-sid-uid-role_num-timestamp-typ  
  17.         String row = sdf.format(new Date(Long.parseLong(datas[4])))  
  18.                 + "-" + datas[0] + "-" + datas[1] + "-" + datas[2]  
  19.                 + "-" + datas[4] + "-" + datas[3];  
  20.         ImmutableBytesWritable rowkey = new ImmutableBytesWritable(  
  21.                 Bytes.toBytes(row));  
  22.         KeyValue kv = new KeyValue(Bytes.toBytes(row),this.CF_KQ.getBytes(), datas[3].getBytes(),Bytes.toBytes(this.ONE));  
  23.         context.write(rowkey, kv);  
  24.         }  
  25. }  


job: 
Java代码   收藏代码
  1. public class GenHFile2 {  
  2.     public static void main(String[] args) {  
  3.         Configuration conf = new Configuration();  
  4.         conf.addResource("myConf.xml");  
  5.         String input = conf.get("input");  
  6.         String output = conf.get("output");  
  7.         String tableName = conf.get("source_table");  
  8.         System.out.println("table : "+tableName);  
  9.         HTable table;  
  10.         try {  
  11.             //运行前,删除已存在的中间输出目录  
  12.             try {  
  13.                 FileSystem fs = FileSystem.get(URI.create(output), conf);  
  14.                 fs.delete(new Path(output),true);  
  15.                 fs.close();  
  16.             } catch (IOException e1) {  
  17.                 e1.printStackTrace();  
  18.             }  
  19.               
  20.             table = new HTable(conf,tableName.getBytes());  
  21.             Job job = new Job(conf);  
  22.             job.setJobName("Generate HFile");  
  23.               
  24.             job.setJarByClass(HFileImportMapper2.class);  
  25.             job.setInputFormatClass(TextInputFormat.class);  
  26.             job.setMapperClass(HFileImportMapper2.class);  
  27.             FileInputFormat.setInputPaths(job, input);  
  28.               
  29. //job.setReducerClass(KeyValueSortReducer.class);  
  30. //job.setMapOutputKeyClass(ImmutableBytesWritable.class);  
  31. //job.setMapOutputValueClass(KeyValue.class);  
  32.             job.getConfiguration().set("mapred.mapoutput.key.class""org.apache.hadoop.hbase.io.ImmutableBytesWritable");  
  33.             job.getConfiguration().set("mapred.mapoutput.value.class""org.apache.hadoop.hbase.KeyValue");  
  34.               
  35. //job.setOutputFormatClass(HFileOutputFormat.class);  
  36. FileOutputFormat.setOutputPath(job, new Path(output));  
  37.     //job.setPartitionerClass(SimpleTotalOrderPartitioner.class);  
  38. HFileOutputFormat.configureIncrementalLoad(job,table);  
  39.             try {  
  40.                 job.waitForCompletion(true);  
  41.             } catch (InterruptedException e) {  
  42.                 e.printStackTrace();  
  43.             } catch (ClassNotFoundException e) {  
  44.                 e.printStackTrace();  
  45.             }  
  46.         } catch (IOException e) {  
  47.             e.printStackTrace();  
  48.         }  
  49.     }  
  50. }  


生成的HFile文件在hdfs的/output目录下,已经根据cf名称建好文件目录: 
Java代码   收藏代码
  1. hdfs://namenode/output/kq/601c5029fb264dc8869a635043c24560  

其中: 
Java代码   收藏代码
  1. HFileOutputFormat.configureIncrementalLoad(job,table);  

根据其源码知道,会自动为job设置好以下参数: 
Java代码   收藏代码
  1. public static void configureIncrementalLoad(Job job, HTable table)  
  2. throws IOException {  
  3.   Configuration conf = job.getConfiguration();  
  4.   
  5.   job.setOutputKeyClass(ImmutableBytesWritable.class);  
  6.   job.setOutputValueClass(KeyValue.class);  
  7.   job.setOutputFormatClass(HFileOutputFormat.class);  
  8.   
  9.   // Based on the configured map output class, set the correct reducer to properly  
  10.   // sort the incoming values.  
  11.   // TODO it would be nice to pick one or the other of these formats.  
  12.   if (KeyValue.class.equals(job.getMapOutputValueClass())) {  
  13.     job.setReducerClass(KeyValueSortReducer.class);  
  14.   } else if (Put.class.equals(job.getMapOutputValueClass())) {  
  15.     job.setReducerClass(PutSortReducer.class);  
  16.   } else if (Text.class.equals(job.getMapOutputValueClass())) {  
  17.     job.setReducerClass(TextSortReducer.class);  
  18.   } else {  
  19.     LOG.warn("Unknown map output value type:" + job.getMapOutputValueClass());  
  20.   }  
  21.   
  22.   conf.setStrings("io.serializations", conf.get("io.serializations"),  
  23.       MutationSerialization.class.getName(), ResultSerialization.class.getName(),  
  24.       KeyValueSerialization.class.getName());  
  25.   
  26.   // Use table's region boundaries for TOP split points.  
  27.   LOG.info("Looking up current regions for table " + Bytes.toString(table.getTableName()));  
  28.   List startKeys = getRegionStartKeys(table);  
  29.   LOG.info("Configuring " + startKeys.size() + " reduce partitions " +  
  30.       "to match current region count");  
  31.   job.setNumReduceTasks(startKeys.size());  
  32.   
  33.   configurePartitioner(job, startKeys);  
  34.   // Set compression algorithms based on column families  
  35.   configureCompression(table, conf);  
  36.   configureBloomType(table, conf);  
  37.   configureBlockSize(table, conf);  
  38.   
  39.   TableMapReduceUtil.addDependencyJars(job);  
  40.   TableMapReduceUtil.initCredentials(job);  
  41.   LOG.info("Incremental table " + Bytes.toString(table.getTableName()) + " output configured.");  
  42. }  


HFileOutputFormat只支持写单个column family,如果有多个cf,则需要写多个job来实现了。 

你可能感兴趣的:(hadoop)