Hbase编程入门之MapReduce

来源:互联网 发布:手机如何申请淘宝直播 编辑:程序博客网 时间:2024/05/01 09:59

refer to: http://blog.csdn.net/darke1014/article/details/8665484

Tips:如果用Eclipse开发,需要加入hadoop所有的jar包以及HBase三个jar包(hbase,zooKooper,protobuf-java)。

下面介绍一下,用mapreduce怎样操作HBase,主要对HBase中的数据进行读取。

案例一:

首先先介绍下如何上传数据,还是以最熟悉到wordcount案例开始,我们的目的是将wordcount的结果存储到Hbase而不是HDFS下。

给出代码:

[java] view plaincopy
  1. package test1;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.StringTokenizer;  
  5.   
  6. import org.apache.hadoop.conf.Configuration;  
  7. import org.apache.hadoop.fs.Path;  
  8. import org.apache.hadoop.io.IntWritable;  
  9. import org.apache.hadoop.io.Text;  
  10. import org.apache.hadoop.mapreduce.Job;  
  11. import org.apache.hadoop.mapreduce.Mapper;  
  12. import org.apache.hadoop.mapreduce.Reducer;  
  13. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
  14. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
  15. import org.apache.hadoop.util.GenericOptionsParser;  
  16. import org.apache.hadoop.hbase.HBaseConfiguration;  
  17. import org.apache.hadoop.hbase.HColumnDescriptor;  
  18. import org.apache.hadoop.hbase.HTableDescriptor;  
  19. import org.apache.hadoop.hbase.client.HBaseAdmin;  
  20. import org.apache.hadoop.hbase.client.Put;  
  21. import org.apache.hadoop.hbase.io.ImmutableBytesWritable;  
  22. import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;  
  23. import org.apache.hadoop.hbase.mapreduce.TableOutputFormat;  
  24. import org.apache.hadoop.hbase.mapreduce.TableReducer;  
  25. import org.apache.hadoop.hbase.util.Bytes;  
  26.   
  27. public class WordCountHBase {  
  28.   
  29.   public static class TokenizerMapper   
  30.        extends Mapper<Object, Text, Text, IntWritable>{  
  31.       
  32.     private final static IntWritable one = new IntWritable(1);  
  33.     private Text word = new Text();  
  34.        
  35.     //map函数没有改变  
  36.     public void map(Object key, Text value, Context context  
  37.                     ) throws IOException, InterruptedException {  
  38.       StringTokenizer itr = new StringTokenizer(value.toString());  
  39.       while (itr.hasMoreTokens()) {  
  40.         word.set(itr.nextToken());  
  41.         context.write(word, one);  
  42.       }  
  43.     }  
  44.   }  

map函数没有改变


[java] view plaincopy
  1. //Reduce类,主要是将键值传到HBase表中  
  2. public static class IntSumReducer   
  3.      extends TableReducer <Text,IntWritable,ImmutableBytesWritable> {  
  4.   private IntWritable result = new IntWritable();  
  5.   
  6.   public void reduce(Text key, Iterable<IntWritable> values,   
  7.                      Context context  
  8.                      ) throws IOException, InterruptedException {  
  9.     int sum = 0;  
  10.     for (IntWritable val : values) {  
  11.       sum += val.get();  
  12.     }  
  13.     result.set(sum);  
  14.     Put put = new Put(key.getBytes());  //put实例化,每一个词存一行  
  15.     //列族为content,列修饰符为count,列值为数目  
  16.     put.add(Bytes.toBytes("content"), Bytes.toBytes("count"), Bytes.toBytes(String.valueOf(sum)));  
  17.     context.write(new ImmutableBytesWritable(key.getBytes()), put);  
  18.   }  
  19. }  

由上面可知IntSumReducer继承自TableReduce,在hadoop里面TableReducer继承Reducer类。它的原型为:TableReducer<KeyIn,Values,KeyOut>可以看出,HBase里面是读出的Key类型是ImmutableBytesWritable,意为不可变类型,因为HBase里所有数据都是用字符串存储的。

[java] view plaincopy
  1.   @SuppressWarnings("deprecation")  
  2. public static void main(String[] args) throws Exception {  
  3.       String tablename  = "wordcount";  
  4.   
  5.       //实例化Configuration,注意不能用 new HBaseConfiguration()了。  
  6.      Configuration conf = HBaseConfiguration.create();  
  7.        
  8.      HBaseAdmin admin = new HBaseAdmin(conf);  
  9.      if(admin.tableExists(tablename)){  
  10.          System.out.println("table exists! recreating ...");  
  11.          admin.disableTable(tablename);  
  12.          admin.deleteTable(tablename);  
  13.      }  
  14.      HTableDescriptor htd = new HTableDescriptor(tablename);  
  15.      HColumnDescriptor hcd = new HColumnDescriptor("content");  
  16.      htd.addFamily(hcd);        //创建列族  
  17.      admin.createTable(htd);    //创建表  
  18.        
  19.     String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();  
  20.     if (otherArgs.length != 1) {  
  21.       System.err.println("Usage: wordcount <in> <out>"+otherArgs.length);  
  22.       System.exit(2);  
  23.     }  
  24.     Job job = new Job(conf, "word count");  
  25.     job.setJarByClass(WordCountHBase.class);  
  26.     job.setMapperClass(TokenizerMapper.class);  
  27.     //job.setCombinerClass(IntSumReducer.class);  
  28.   
  29.     FileInputFormat.addInputPath(job, new Path(otherArgs[0]));  
  30.   
  31.     //此处的TableMapReduceUtil注意要用hadoop.hbase.mapreduce包中的,而不是hadoop.hbase.mapred包中的  
  32.     TableMapReduceUtil.initTableReducerJob(tablename, IntSumReducer.class, job);      
  33.   
  34.     //key和value到类型设定最好放在initTableReducerJob函数后面,否则会报错  
  35.     job.setOutputKeyClass(Text.class);  
  36.     job.setOutputValueClass(IntWritable.class);  
  37.       
  38.     System.exit(job.waitForCompletion(true) ? 0 : 1);  
  39.   }  
  40. }  
在job配置的时候没有设置 job.setReduceClass(); 而是用 TableMapReduceUtil.initTableReducerJob(tablename, IntSumReducer.class, job); 来执行reduce类。

需要注意的是此处的TableMapReduceUtil是hadoop.hbase.mapreduce包中的,而不是hadoop.hbase.mapred包中的,否则会报错。


案例二:

下面再介绍下如何进行读取,读取数据时比较简单,编写Mapper函数,读取<key,value>值就行了,Reducer函数直接输出得到的结果就行了。

[java] view plaincopy
  1. package test1;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.StringTokenizer;  
  5.   
  6. import org.apache.hadoop.conf.Configuration;  
  7. import org.apache.hadoop.fs.Path;  
  8. import org.apache.hadoop.io.IntWritable;  
  9. import org.apache.hadoop.io.Text;  
  10. import org.apache.hadoop.mapreduce.Job;  
  11. import org.apache.hadoop.mapreduce.Mapper;  
  12. import org.apache.hadoop.mapreduce.Reducer;  
  13. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
  14. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
  15. import org.apache.hadoop.util.GenericOptionsParser;  
  16. import org.apache.hadoop.hbase.HBaseConfiguration;  
  17. import org.apache.hadoop.hbase.HColumnDescriptor;  
  18. import org.apache.hadoop.hbase.HTableDescriptor;  
  19. import org.apache.hadoop.hbase.client.HBaseAdmin;  
  20. import org.apache.hadoop.hbase.client.Put;  
  21. import org.apache.hadoop.hbase.client.Result;  
  22. import org.apache.hadoop.hbase.client.Scan;  
  23. import org.apache.hadoop.hbase.io.ImmutableBytesWritable;  
  24. import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;  
  25. import org.apache.hadoop.hbase.mapreduce.TableMapper;  
  26. import org.apache.hadoop.hbase.mapreduce.TableOutputFormat;  
  27. import org.apache.hadoop.hbase.mapreduce.TableReducer;  
  28. import org.apache.hadoop.hbase.util.Bytes;  
  29.   
  30. import test1.WordCount.IntSumReducer;  
  31.   
  32. import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry.Entry;  
  33.   
  34. public class ReadHBase {  
  35.   
  36.   public static class TokenizerMapper   
  37.        extends TableMapper<Text, Text>{  
  38.        
  39.     public void map(ImmutableBytesWritable row, Result values, Context context  
  40.                     ) throws IOException, InterruptedException {  
  41.         StringBuffer sb = new StringBuffer("");  
  42.         for(java.util.Map.Entry<byte[],byte[]> value : values.getFamilyMap(  
  43.                 "content".getBytes()).entrySet()){  
  44.             String str = new String(value.getValue());  //将字节数组转换成String类型,需要new String();  
  45.             if(str != null){  
  46.                 sb.append(new String(value.getKey()));  
  47.                 sb.append(":");  
  48.                 sb.append(str);  
  49.             }  
  50.             context.write(new Text(row.get()), new Text(new String(sb)));  
  51.               
  52.         }  
  53.   
  54.     }  
  55.   }  
  56.     
  57.     

map函数继承到TableMapper接口,从result中读取查询结果。


[java] view plaincopy
  1. public static class IntSumReducer   
  2.        extends Reducer <Text,Text,Text,Text> {  
  3.     private Text result = new Text();  
  4.   
  5.     public void reduce(Text key, Iterable<Text> values,   
  6.                        Context context  
  7.                        ) throws IOException, InterruptedException {  
  8.   
  9.       for (Text val : values) {  
  10.           result.set(val);  
  11.           context.write(key,result);  
  12.       }  
  13.   
  14.     }  
  15.   }  
reduce函数没有改变,直接输出到文件中即可

[java] view plaincopy
  1. @SuppressWarnings("deprecation")  
  2. blic static void main(String[] args) throws Exception {  
  3.  String tablename  = "wordcount";  
  4.   
  5.  //实例化Configuration,注意不能用 new HBaseConfiguration()了。  
  6. Configuration conf = HBaseConfiguration.create();  
  7.   
  8.   String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();  
  9.   if (otherArgs.length != 2) {  
  10.     System.err.println("Usage: wordcount <in> <out>"+otherArgs.length);  
  11.     System.exit(2);  
  12.   }  
  13.   Job job = new Job(conf, "word count");  
  14.   job.setJarByClass(ReadHBase.class);  
  15.   FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));  
  16.   job.setReducerClass(IntSumReducer.class);  
  17.     
  18.   //此处的TableMapReduceUtil注意要用hadoop.hbase.mapreduce包中的,而不是hadoop.hbase.mapred包中的  
  19.   Scan scan = new Scan(args[0].getBytes());  
  20.   TableMapReduceUtil.initTableMapperJob(tablename, scan, TokenizerMapper.class, Text.class, Text.class, job);  
  21.   
  22.   System.exit(job.waitForCompletion(true) ? 0 : 1);  
  23. }  
其中我输入的两个参数分别是“aa ouput”   分别是开始查找的行(这里为从“aa”行开始找),和输出文件到存储路径(这里为存到HDFS目录到output文件夹下)

要注意的是,在JOB的配置中需要实现initTableMapperJob方法。与第一个例子类似,    

在job配置的时候不用设置 job.setMapperClass(); 而是用 TableMapReduceUtil.initTableMapperJob(tablename, scan, TokenizerMapper.class, Text.class, Text.class, job);来执行mapper类。Scan实例是查找的起始行。


0 0
原创粉丝点击