一、准备
- 让Hadoop加载HBase的jar包
- 法一:将HBase中的所有的jar包都导入到Hadoop的lib目录下
- 法二:将HBase的包地址写到Hadoop的hadoop-env.sh文件中
export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:HBase的目录/lib/*
二、运行官方MapReduce任务
hadoop jar hbase-server-1.3.1.jar CellCounter t1 /hbasemr/cellcount
hadoop jar hbase-server-1.3.1.jar rowcounter t1
- 案例三:向HBase导入数据
- 向hbase中导入数据,需要手动建表,需要把数据上传到HDFS,注意数据中字段的顺序要和-Dimporttsv.columns的顺序一致
- HBASE_ROW_KEY:代表rowkey列
hadoop jar hbase-server-1.3.1.jar importtsv -Dimporttsv.columns=HBASE_ROW_KEY,info:name,info:age,info:gender t2 /hbaseimport
三、自定义MapReduce任务
3.1 案例一
- 需求:MR读取hbase中t2表的部分数据,写入到t4表中
- Mapper
package hbase.mr.tiger;
/*
* 1、MR读取hbase中t2表的部分数据,写入到t4表中
* 读入输入目录中的数据(t2) --- Map --- Reduce --- 写出到指定的目录(t4)
*
* 2、目前读取的是HBase中的数据,而不是文本文件,所以不能使用默认的TextInputFormat,自然RecordReader泛型无法确定
* 需要先确定什么样的输入格式可以读取HBase中的表
* 在HBase中默认使用TableInputFormat输入格式,
* 切片,一个region切一片
* RecordReader:RecordReader<ImmutableBytesWritable, Result>
* ImmutableBytesWritable:rowkey
* Result:一行的数据
*
* 3、输出的数据应该是一个put对象
* 在Maper中,数据如果需要排序,必须作为key,如果不需要排序可以作为value
*
* 4、如果Mapper输出的value是put类型,会自动设置Combiner
* 无法避免设置设置Combiner时,可以让Combiner的逻辑无法执行
* 保证输出的key不能相等,
*
* 5、Hadoop MR处理的数据都必须是key-value
* 在Hadoop中,只要有Reducer,那么此时key-value必须实现序列化
* Wriable,key实现WritableComarable
* value实现Writable
*
* 为什么Put没有实现Wriable,程序依然没有报错
* HBase自己提供了序列化器
*
* */
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.TableMapper;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.Text;
import java.io.IOException;
public class Example1Mapper extends TableMapper<Text , Put> {
private Text out_key = new Text();
@Override
protected void map(ImmutableBytesWritable key, Result value, Context context) throws IOException, InterruptedException {
out_key.set(Bytes.toString(key.copyBytes()));
// 构建put对象,并且封装了rowkey
Put put = new Put(key.copyBytes());
Cell[] rawCells = value.rawCells();
for (Cell rawCell : rawCells) {
if (Bytes.toString(CellUtil.cloneFamily(rawCell)).equals("info")
&& Bytes.toString(CellUtil.cloneQualifier(rawCell)).equals("age")
&& Bytes.toString(CellUtil.cloneValue(rawCell)).equals("20")) {
//
// 把符合要求的一行所有的单元格放入到put对象中
for (Cell cell : rawCells) {
put.add(cell);
}
// 把整个put写出
context.write(out_key, put);
}
}
}
}
package hbase.mr.tiger;
/*
* 1、Reducer输出的类型必须是Mutation,是固定的
* Mutation是所有写数据类型的父类
*
*
* Reducer的任务就是将Mapper输出所的所有记录写出
* */
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.mapreduce.TableReducer;
import org.apache.hadoop.io.Text;
public class Example1Reducer extends TableReducer<Text, Put, Text> {
}
package hbase.mr.tiger;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import java.io.IOException;
public class Example1Driver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
// 创建一个job的Configuration
Configuration conf = HBaseConfiguration.create();
// 创建一个job
Job job = Job.getInstance(conf);
job.setJobName("example1");
job.setJarByClass(Example1Driver.class);
Scan scan = new Scan();
// 配置job Mapper配置
TableMapReduceUtil.initTableMapperJob("t2", scan, Example1Mapper.class, Text.class, Put.class, job);
// 配置job Reducer配置
TableMapReduceUtil.initTableReducerJob("t4", Example1Reducer.class, job);
// 运行
job.waitForCompletion(true);
}
}
3.2 案例二
- 需求:MR读取HDFS中的数据,写入到hbase中
- Mapper
package hbase.mr.hdfstohbase;
/*
* 1、MR读取HDFS中的数据,写入到hbase中
* InputFormat无需使用TableInputFormat
*
* */
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException;
public class Example2Mapper extends Mapper<LongWritable, Text, Text, Put> {
private Text out_key = new Text();
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String[] words = value.toString().split("\t");
// 封装rowkey列
out_key.set(words[0]);
Put put = new Put(Bytes.toBytes(words[0]));
put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("category"), Bytes.toBytes(words[1]));
context.write(out_key, put);
}
}
package hbase.mr.hdfstohbase;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.mapreduce.TableReducer;
import org.apache.hadoop.io.Text;
public class Example2Reducer extends TableReducer<Text, Put, Text> {
}
package hbase.mr.hdfstohbase;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import java.io.IOException;
public class Example2Driver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
// 创建一个job的Configuration
Configuration conf = HBaseConfiguration.create();
// 创建一个job
Job job = Job.getInstance(conf);
job.setJobName("example2");
job.setJarByClass(Example2Driver.class);
// 设置job使用的Mapper的类型
job.setMapperClass(Example2Mapper.class);
// 设置job使用的Mapper的输出的类型
job.setMapOutputKeyClass(Text.class);
job.setOutputValueClass(Put.class);
// 设置输入目录
FileInputFormat.setInputPaths(job, new Path("hdfs://master:9000/hive/warehouse/movie_info/data2"));
// 配置job Reducer配置
TableMapReduceUtil.initTableReducerJob("t5", Example2Reducer.class, job);
// 运行
job.waitForCompletion(true);
}
}