使用HBase的API中的Put是最直接的方法,用法也很容易学习。但针对大部分情况,它并非都是最高效的方式。
下面例子的数据是通过我书写输入,当然也可以通过mysql数据里得到数据后批量put到hbase,或者MapReduce 读取hdfs上的文件,以put的方式在map中完成数据写入。在这个项目中,也可以在网上爬到数据后,直接put到hbase。 不过在我看来,如果把获取数据(就是爬虫爬数据阶段),录入数据库。这两步一起做会比较繁琐,错了一个地方,可能每个地方都要变动。而把两步分开,这样更模块化,易管理易维护。
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
public class PutDemo {
public static void main(String[] args)throws IOException {
Configuration conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", "192.168.6.250,192.168.6.251,192.168.6.252");
HBHelper helper = new HBHelper(conf);
helper.dropTable("person3");
helper.createTable("person3", "info");
helper.insterRow("person3", "row1", "info", "name", "小明");
helper.insterRow("person3", "row1", "info", "majar", "软件技术");
helper.insterRow("person3", "row1", "info", "name", "Malik");
helper.scanData("person3");
helper.close();
}
}
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.util.Bytes;
public class HBHelper {
private static Connection connection = null;
private static Admin admin = null;
public HBHelper (Configuration conf) {
try {
connection = HBHelper.getConnInstance(conf);
} catch (Exception e) {
e.printStackTrace();
}
}
private static synchronized Connection getConnInstance(Configuration conf)throws IOException{
if(connection==null){
try{
connection = ConnectionFactory.createConnection(conf);
admin = connection.getAdmin();
}
catch (IOException e) {
e.printStackTrace();
}
System.out.println("连接数据库成功");
}
return connection;
}
public void close(){
try {
if(null != admin)
admin.close();
if(null != connection)
connection.close();
System.out.println("关闭数据库成功");
} catch (IOException e) {
e.printStackTrace();
}
}
public void createTable(String table, String... colfams)
throws IOException {
createTable(table, null, colfams);
}
public void createTable(String table, byte[][] splitKeys, String... colfams)
throws IOException {
HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(table));
for (String cf : colfams) {
HColumnDescriptor coldef = new HColumnDescriptor(cf);
desc.addFamily(coldef);
}
if (splitKeys != null) {
admin.createTable(desc, splitKeys);
} else {
admin.createTable(desc);
}
}
/**
* @Title disableTable
* @Description 禁用table
* @param table
* @throws IOException
*/
public void disableTable(String table) throws IOException {
// admin.disableTable(table);
admin.disableTable(TableName.valueOf(table));
}
public boolean existsTable(String table)
throws IOException {
return admin.tableExists(TableName.valueOf(table));
}
/**
* @Title dropTable
* @Description dropTable
* @param table
* @throws IOException
*/
public void dropTable(String table) throws IOException {
if (existsTable(table)) {
disableTable(table);
admin.deleteTable(TableName.valueOf(table));
}
}
public void insterRow(String tableName,String rowkey,String colFamily,String col,String val) throws IOException {
Table table = connection.getTable(TableName.valueOf(tableName));
Put put = new Put(Bytes.toBytes(rowkey));
put.addColumn(Bytes.toBytes(colFamily), Bytes.toBytes(col), Bytes.toBytes(val));
table.put(put);
//批量插入
/* List putList = new ArrayList();
puts.add(put);
table.put(putList);*/
table.close();
}
//格式化输出
public void showCell(Result result){
Cell[] cells = result.rawCells();
for(Cell cell:cells){
System.out.println("RowName:"+new String(CellUtil.cloneRow(cell))+", "
+"Timetamp:"+cell.getTimestamp()+", "
+"column Family:"+new String(CellUtil.cloneFamily(cell))+", "
+"列修饰符:"+new String(CellUtil.cloneQualifier(cell))+", "
+"value:"+new String(CellUtil.cloneValue(cell))+" ");
}
}
//批量查找数据
public void scanData(String tableName/*,String startRow,String stopRow*/)throws IOException{
Table table = connection.getTable(TableName.valueOf(tableName));
Scan scan = new Scan();
//scan.setStartRow(Bytes.toBytes(startRow));
//scan.setStopRow(Bytes.toBytes(stopRow));
ResultScanner resultScanner = table.getScanner(scan);
for(Result result : resultScanner){
showCell(result);
}
table.close();
}
}
importtsv 通过运行一个MapReduce Job,将数据从TSV文件(在数据库里导出的csv或tsv文件)中直接写入HBase的表或者写入一个HBase的自有格式数据文件。
HBase提供importtsv工具支持从TSV文件中将数据导入HBase。使用该工具将文本数据加载至HBase十分高效,因为它是通过MapReduce Job来实施导入的。哪怕是要从现有的关系型数据库中加载数据,也可以先将数据导入文本文件中,然后使用importtsv 工具导入HBase。在导入海量数据时,这个方式运行的很好,因为导出数据比在关系型数据库中执行SQL快很多。
命令:
格式:hbase [类] [分隔符] [行键,列族] [表] [导入文件]
hbase org.apache.hadoop.hbase.mapreduce.ImportTsv -Dimporttsv.separator=”,”
-Dimporttsv.columns=HBASE_ROW_KEY,cf hbase-tb1-001 /data.csv
data.csv数据如下
1,"Tony"
2,"Ivy"
3,"Tom"
4,"Spark"
5,"Storm
把data.csv上传到hdfs上
[hadoop@master ~]$ hdfs dfs -put /tmp/hbase-input
建表
hbase(main):001:0> create 'hbase-tb1-001','cf'
0 row(s) in 3.1120 seconds
=> Hbase::Table - hbase-tb1-001
运行命令
[hadoop@master ~]$ hbase org.apache.hadoop.hbase.mapreduce.ImportTsv -Dimporttsv.separator=","
-Dimporttsv.columns=HBASE_ROW_KEY,cf hbase-tb1-001 /tmp/hbase-input/data.csv
查看结果
hbase(main):003:0> scan 'hbase-tb1-001'
ROW COLUMN+CELL
1 column=cf:, timestamp=1436152834178, value="Tony"
2 column=cf:, timestamp=1436152834178, value="Ivy"
3 column=cf:, timestamp=1436152834178, value="Tom"
4 column=cf:, timestamp=1436152834178, value="Spark"
5 column=cf:, timestamp=1436152834178, value="Storm"
5 row(s) in 0.1490 seconds
HBase支持bulkload的入库方式,它是利用hbase的数据信息按照特定格式存储在hdfs内这一原理,直接在HDFS中生成持久化的HFile数据格式文件,然后上传至合适位置,即完成巨量数据快速入库的办法。配和mapreduce完成,高效便捷,而且不占用region资源,增添负载,在大数据量写入时,能极大的提高写入效率,并降低对HBase节点的写入压力。
通过使用先生成HFile,然后再BulkLoad到HBase的方式来替代之前直接调用HTableOutputFormat的方法有如下的好处:
1、消除了对HBase集群的插入压力
2、提高了Job的运行速度,降低了Job的执行时间
利用completebulkload将数据导入到HBase
运行过程发现出现错误,解决办法是在hadoo-env.sh 里给hadoopclass添加hbase下lib的jar路径。
export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:/home/hadoop/hbase-1.2.4/lib/*
data.csv数据如下
1,”Tony”
2,”Ivy”
3,”Tom”
4,”Spark”
5,”Storm
把data.csv上传到hdfs上
[hadoop@master ~]$ hdfs dfs -put /tmp/hbase-input
1. 先通过lmportTsv生成HFile
[hadoop@master hadoop]$hbase org.apache.hadoop.hbase.mapreduce.ImportTsv -Dimporttsv.separator="," -Dimporttsv.bulk.output=/chenglianlong/hfile_tmp -Dimporttsv.columns=HBASE_ROW_KEY,cf hbase-tbl-002 /tmp/hbase-input/data.csv
命令:hbase [类] [分隔符] [输出存储路径] [行键,列族] [表] [导入原始数据文件]
以上的指令,它会主动创建表hbase-tbl-002和文件夹hfile_tmp。
2. 通过completebulkload将数据导入表hbase-tbl-002
[hadoop@master hadoop]$ hadoop jar /home/hadoop/hbase-1.2.4/lib/hbase-server-1.2.4.jar completebulkload /chenglianlong/hfile_tmp hbase-tbl-002
3. 查看结果
hbase(main):001:0> scan 'hbase-tbl-002'
ROW COLUMN+CELL
1 column=cf:, timestamp=1487579771424, value="Tony"
2 column=cf:, timestamp=1487579771424, value="Ivy"
3 column=cf:, timestamp=1487579771424, value="Tom"
4 column=cf:, timestamp=1487579771424, value="Spark"
5 column=cf:, timestamp=1487579771424, value="Storm"
5 row(s) in 0.6490 seconds