HBase擅长存储数据,但不擅长计算分析数据,但是它可以借用其他组件(mapreduce/spark),使用官方提供的hbase-api来实现计算分析数据功能。
hbase-server.jar
下面官方提供的一个Hbase操作MR的例子,此例子作用是对一张表的rowkey进行计数。
- 解决HBase与MapReduce的依赖包问题。
# 显示hbase需要的MapReduce Jar包
hbase mapredcp
# 环境变量
export HBASE_HOME="hbase安装目录"
export HADOOP_HOME="HADOOP安装目录"
# 注意是HADOOOP_CLASSPATH
export HADOOP_CLASSPATH=`${HBASE_HOME}/bin/hbase mapredcp`
上面的配置可以写入到hadoop-env.sh
- hbase安装目录/lib下,有个hbase-server-1.4.9.jar,是官方提供的工具包
# 此处执行hbase-server.jar,此jar包需要用到上面导入的mapredcp包。rowcounter是官方提供的计数rowkey的类名。
/home/even/hd/hadoop-2.8.4/bin/yarn jar lib/hbase-server-1.4.9.jar rowcounter table1
table1的数据:
运行MapReduce程序后的结果:
除了上面的rowcounter外,官方还提供了其他命令,如下面的导入数据命令。
/home/even/hd/hadoop-2.8.4/bin/yarn jar lib/hbase-server-1.4.9.jar importtsc -Dimporttsv.columns=HBASE_ROW_KEY,info:name,info:id table1 hdfs://hd-even-01:9000/tablein/
其他的命令可查看HBase-MapReduce官方文档
HBase-MR API
HBase针对MR提供了一套api。
例子1——HBase表1到HBase表2
下面例子中是要把table1的info列族的name列的数据导入table2表的info1列族的id列,以展示此套api的使用。
- HBaseMapper.java,查询出指定的列并输出到Reducer
package com.even.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 java.io.IOException;
/**
* des: TableMapper是HBase提供的api
* ImmutableBytesWritable类似之前的LongWritable,表示起始偏移量。put表示封装的一条一条数据,需要导入到Reduce阶段
* author: Even
* create date:2019/1/30
*/
public class HBaseMapper extends TableMapper<ImmutableBytesWritable, Put> {
@Override
protected void map(ImmutableBytesWritable key, Result value, Context context) throws IOException, InterruptedException {
/*1,读取数据,拿到一个rowkey的数据,根据key得到put*/
Put put = new Put(key.get());
/*2,遍历出每个列并筛选需要的*/
for (Cell cell : value.rawCells()) {
/*获取列族*/
String cf = Bytes.toString(CellUtil.cloneFamily(cell));
if ("info".equals(cf)) {
/*获取列*/
if ("name".equals(Bytes.toString(CellUtil.cloneQualifier(cell))))
/*获取info列族的name列的数据,并导入到另一张表的info1列族的id列*/
put.addColumn(Bytes.toBytes("info1"), Bytes.toBytes("id"), CellUtil.cloneValue(cell));
}
}
context.write(key, put