将数据导入到HBase有三种方式:(1) Mapreduce,输出为TableOutputFormat.(2) 用HBase API .(3)Bulk Loading。对于大量的数据入库,第三种数据是最为有效的。

下图描述了Bulk Loading的过程:先将数据(MySQL ,Oracle ,文本文件等)加载到HDFS,通过MapReduce 将数据做成HFile (HFileOutPutForm)。然后使用HBase提供的CompleteBulkLoad(LoadIncrementalHFiles)工具加载到HBase中,这个过程很快,而且不很耗内存,不影响在线的Hbase
集群的正常操作。因为这个过程不需要结果WAL 和Memstore.

注意事项:

(1)配置一个total order partitioner。

(2)reduce 个数要和表的region 数目匹配。

(3)MR 输出的Key/Value 类型要和HFileOutPutFormat的匹配。

(4)reduce 采用KeyValueSortReducer 或者PutSortReducer。

应用场景:

(1)集群上线,原始数据集加载。

(2)数据增量。需要定期将MySql(Oracle) 的数据导入HBase。

(3)经常性的大批量入库。

对于CSV文件的加载:

hadoop jar   /usr/lib/hbase/hbase-0.94.6-cdh4.3.0-
security.jar importtsv
-Dimporttsv.separator=,
-Dimporttsv.bulk.output=output
-Dimporttsv.columns=HBASE_ROW_KEY,f:count wordcount word_count.csv

该文件的数据格式为---> rowkey,列:值 。

导入到的表名为wordcount ,数据文件为word_count.csv

这样做,不会生成wordcount表。

执行

hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles output wordcount 

入库完成。

hadoop jar   /usr/lib/hbase/hbase-0.94.6-cdh4.3.0-
security.jar importtsv
-Dimporttsv.separator=,
-Dimporttsv.columns=HBASE_ROW_KEY,f:count wordcount word_count.csv

这样做一步到位,直接入库。

或者用

HADOOP_CLASSPATH=`${HBASE_HOME}/bin/hbase classpath` ${HADOOP_HOME}/bin/hadoop jar ${HBASE_HOME}/hbase-VERSION.jar completebulkload <hdfs://storefileoutput> <tablename>

同样 一步到位,直接入库。

下面是一个MR生成HFile的例子:


import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.HFileOutputFormat;
import org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;
/**
* HBase bulk import example<br>
* Data preparation MapReduce job driver
* <ol>
* <li>args[0]: HDFS input path
* <li>args[1]: HDFS output path
* <li>args[2]: HBase table name
* </ol>
*/
public class Driver {
  public static void main(String[] args) throws Exception {
    Configuration conf = new Configuration();
    args = new GenericOptionsParser(conf, args).getRemainingArgs();
    /*
* NBA Final 2010 game 1 tip-off time (seconds from epoch)
* Thu, 03 Jun 2010 18:00:00 PDT
*/
    conf.setInt("epoch.seconds.tipoff", 1275613200);
    conf.set("hbase.table.name", args[2]);
    
    // Load hbase-site.xml
    HBaseConfiguration.addHbaseResources(conf);
    Job job = new Job(conf, "HBase Bulk Import Example");
    job.setJarByClass(HBaseKVMapper.class);
    job.setMapperClass(HBaseKVMapper.class);
    job.setMapOutputKeyClass(ImmutableBytesWritable.class);
    job.setMapOutputValueClass(KeyValue.class);
    job.setInputFormatClass(TextInputFormat.class);
    HTable hTable = new HTable(args[2]);
    
    // Auto configure partitioner and reducer
    HFileOutputFormat.configureIncrementalLoad(job, hTable);
    FileInputFormat.addInputPath(job, new Path(args[0]));
    FileOutputFormat.setOutputPath(job, new Path(args[1]));
    job.waitForCompletion(true);
  }
}
import java.io.IOException;
import java.util.Locale;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import au.com.bytecode.opencsv.CSVParser;
/**
* HBase bulk import example
* <p>
* Parses Facebook and Twitter messages from CSV files and outputs
* <ImmutableBytesWritable, KeyValue>.
* <p>
* The ImmutableBytesWritable key is used by the TotalOrderPartitioner to map it
* into the correct HBase table region.
* <p>
* The KeyValue value holds the HBase mutation information (column family,
* column, and value)
*/
public class HBaseKVMapper extends
    Mapper<LongWritable, Text, ImmutableBytesWritable, KeyValue> {
  final static byte[] SRV_COL_FAM = "srv".getBytes();
  final static int NUM_FIELDS = 16;
  CSVParser csvParser = new CSVParser();
  int tipOffSeconds = 0;
  String tableName = "";
  DateTimeFormatter p = DateTimeFormat.forPattern("MMM dd, yyyy HH:mm:ss")
      .withLocale(Locale.US).withZone(DateTimeZone.forID("PST8PDT"));
  ImmutableBytesWritable hKey = new ImmutableBytesWritable();
  KeyValue kv;
  /** {@inheritDoc} */
  @Override
  protected void setup(Context context) throws IOException,
      InterruptedException {
    Configuration c = context.getConfiguration();
    tipOffSeconds = c.getInt("epoch.seconds.tipoff", 0);
    tableName = c.get("hbase.table.name");
  }
  /** {@inheritDoc} */
  @Override
  protected void map(LongWritable key, Text value, Context context)
      throws IOException, InterruptedException {
    if (value.find("Service,Term,") > -1) {
      // Skip header
      return;
    }
    String[] fields = null;
    try {
      fields = csvParser.parseLine(value.toString());
    } catch (Exception ex) {
      context.getCounter("HBaseKVMapper", "PARSE_ERRORS").increment(1);
      return;
    }
    if (fields.length != NUM_FIELDS) {
      context.getCounter("HBaseKVMapper", "INVALID_FIELD_LEN").increment(1);
      return;
    }
    // Get game offset in seconds from tip-off
    DateTime dt = null;
    try {
      dt = p.parseDateTime(fields[9]);
    } catch (Exception ex) {
      context.getCounter("HBaseKVMapper", "INVALID_DATE").increment(1);
      return;
    }
    int gameOffset = (int) ((dt.getMillis() / 1000) - tipOffSeconds);
    String offsetForKey = String.format("%04d", gameOffset);
    String username = fields[2];
    if (username.equals("")) {
      username = fields[3];
    }
    // Key: e.g. "1200:twitter:jrkinley"
    hKey.set(String.format("%s:%s:%s", offsetForKey, fields[0], username)
        .getBytes());
    // Service columns
    if (!fields[0].equals("")) {
      kv = new KeyValue(hKey.get(), SRV_COL_FAM,
          HColumnEnum.SRV_COL_SERVICE.getColumnName(), fields[0].getBytes());
      context.write(hKey, kv);
    }
    if (!fields[1].equals("")) {
      kv = new KeyValue(hKey.get(), SRV_COL_FAM,
          HColumnEnum.SRV_COL_TERM.getColumnName(), fields[1].getBytes());
      context.write(hKey, kv);
    }
    if (!fields[2].equals("")) {
      kv = new KeyValue(hKey.get(), SRV_COL_FAM,
          HColumnEnum.SRV_COL_USERNAME.getColumnName(), fields[2].getBytes());
      context.write(hKey, kv);
    }
    if (!fields[3].equals("")) {
      kv = new KeyValue(hKey.get(), SRV_COL_FAM,
          HColumnEnum.SRV_COL_NAME.getColumnName(), fields[3].getBytes());
      context.write(hKey, kv);
    }
    if (!fields[4].equals("")) {
      kv = new KeyValue(hKey.get(), SRV_COL_FAM,
          HColumnEnum.SRV_COL_UPDATE.getColumnName(), fields[4].getBytes());
      context.write(hKey, kv);
    }
    if (!fields[9].equals("")) {
      kv = new KeyValue(hKey.get(), SRV_COL_FAM,
          HColumnEnum.SRV_COL_TIME.getColumnName(), fields[9].getBytes());
      context.write(hKey, kv);
    }
    context.getCounter("HBaseKVMapper", "NUM_MSGS").increment(1);
    /*
* Output number of messages per quarter and before/after game. This should
* correspond to the number of messages per region in HBase
*/
    if (gameOffset < 0) {
      context.getCounter("QStats", "BEFORE_GAME").increment(1);
    } else if (gameOffset < 900) {
      context.getCounter("QStats", "Q1").increment(1);
    } else if (gameOffset < 1800) {
      context.getCounter("QStats", "Q2").increment(1);
    } else if (gameOffset < 2700) {
      context.getCounter("QStats", "Q3").increment(1);
    } else if (gameOffset < 3600) {
      context.getCounter("QStats", "Q4").increment(1);
    } else {
      context.getCounter("QStats", "AFTER_GAME").increment(1);
    }
  }
}


/**
* HBase table columns for the 'srv' column family
*/
public enum HColumnEnum {
  SRV_COL_SERVICE ("service".getBytes()),
  SRV_COL_TERM ("term".getBytes()),
  SRV_COL_USERNAME ("username".getBytes()),
  SRV_COL_NAME ("name".getBytes()),
  SRV_COL_UPDATE ("update".getBytes()),
  SRV_COL_TIME ("pdt".getBytes());
 
  private final byte[] columnName;
  
  HColumnEnum (byte[] column) {
    this.columnName = column;
  }
  public byte[] getColumnName() {
    return this.columnName;
  }
}

HBase Bulk Loading的更多相关文章

  1. How-to: Use HBase Bulk Loading, and Why

    How-to: Use HBase Bulk Loading, and Why http://blog.cloudera.com/blog/2013/09/how-to-use-hbase-bulk- ...

  2. How To Use Hbase Bulk Loading

    最近在学习hbase,学到利用如何将数据导入到hbase中,采用的方式是批量导入:bulk load的方法,中间出现了一些问题,下面将执行的步骤记录一下,以供日后查阅: 说明:导入的方式是将csv文件 ...

  3. HBase高速导入数据--BulkLoad

    Apache HBase是一个分布式的.面向列的开源数据库.它能够让我们随机的.实时的訪问大数据.可是如何有效的将数据导入到HBase呢?HBase有多种导入数据的方法.最直接的方法就是在MapRed ...

  4. 通过BulkLoad的方式快速导入海量数据

    摘要 加载数据到HBase的方式有多种,通过HBase API导入或命令行导入或使用第三方(如sqoop)来导入或使用MR来批量导入(耗费磁盘I/O,容易在导入的过程使节点宕机),但是这些方式不是慢就 ...

  5. Sqoop学习之路 (一)

    一.概述 sqoop 是 apache 旗下一款“Hadoop 和关系数据库服务器之间传送数据”的工具. 核心的功能有两个: 导入.迁入 导出.迁出 导入数据:MySQL,Oracle 导入数据到 H ...

  6. Hadoop生态圈-Sqoop部署以及基本使用方法

    Hadoop生态圈-Sqoop部署以及基本使用方法 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Sqoop(发音:skup)是一款开源的工具,主要用于在Hadoop(Hive)与 ...

  7. sqoop导入数据

    来源https://www.cnblogs.com/qingyunzong/p/8807252.html 一.概述 sqoop 是 apache 旗下一款“Hadoop 和关系数据库服务器之间传送数据 ...

  8. 【Sqoop学习之二】Sqoop使用

    环境 sqoop-1.4.6 一.基本命令1.帮助命令 [root@node101 ~]# sqoop help Warning: /usr/local/sqoop-/../hbase does no ...

  9. Bulk Load-HBase数据导入最佳实践

    一.概述 HBase本身提供了非常多种数据导入的方式,通常有两种经常使用方式: 1.使用HBase提供的TableOutputFormat,原理是通过一个Mapreduce作业将数据导入HBase 2 ...

随机推荐

  1. SQL LOADER使用

    转自huan.gu专栏:http://blog.csdn.net/gh320/article/details/17048907 1.执行的命令 sqlldr 数据库用户名/密码 control=控制文 ...

  2. activiti 配置节点 连线信息获取

    1.1.1. 前言 当使用eclipse插件进行流程设计的时候,部署流程之后,我们如何获取我们定义的所有的节点.连线.关口等配置信息呢?有的人看到这个需求,不免窃喜,这不很简单嘛,重新打来bmpn中定 ...

  3. Android的log日志知识点剖析

    log类的继承结构 Log public final class Log extends Object java.lang.Object ↳ android.util.Log log日志的常用方法 分 ...

  4. java虚拟机 jvm 出入java栈 栈空间内存分配

    java栈空间是一块线程私有的内存空间,java堆和程序数据密切相关,那么java栈就是和线程执行密切相关.线程最基本的执行行为就是函数的调用.每次函数调用其实是通过java栈传递数据的. 数据结构中 ...

  5. 剑指offer面试题5 从头到尾打印链表(java)

    注:(1)这里体现了java数据结构与C语言的不同之处 (2)栈的操作直接利用stack进行 package com.xsf.SordForOffer; import java.util.Stack; ...

  6. 剑指Offer——巧妙使用sort(List<T>,Comparator<? super T>)比较器

    剑指Offer--巧妙使用sort(List<T>,Comparator<? super T>)比较器 先入为主 package cn.edu.ujn.offersword; ...

  7. antlr v4 使用指南连载2——准备环境

    antlr v4 开发环境         从上一篇文章的例子中可以知道,antlr有一套自己的语法来声明目标语言的语法,因此它本身就需要编译或者使用antlr提供的api来读取这些语法规则,并使之可 ...

  8. OpenMP基础----以图像处理中的问题为例

        OpenMP2.5规范中,对于可以多线程执行的循环有如下5点约束: 1.循环语句中的循环变量必须是有符号整形,如果是无符号整形就无法使用,OpenMP3.0中取消了这个约束 2.循环语句中的比 ...

  9. 【设计模式】java设计模式总述及观察者模式

    今天在准备腾讯的面试时想起来要复习一下设计模式,而刚好前几天在参加网易的在线考试的时候,也出了一道关于设计模式的选择题,主要是考察观察者模式,虽然那道题自己做对了,但觉得还是应该好好总结一下设计模式的 ...

  10. java加载外部文件数据到代码中:外部数据文件放到jar包中,调用方法getResourceAsStream

    任务要将数据文件geo.txt加载进行.因为是别人写的总体项目,不能乱动位置.只能将geo.txt打包到jar中某目录.比如,放到.class文件下怎么加载:http://riddickbryant. ...