将数据导入到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. tomcat生命周期的管理——生命周期统一接口Lifecycle

    我们知道Tomcat的架构设计是清晰的.模块化的,其拥有很多组件,假如我们要启动Tomcat,可以一个一个启动组件,但这样启动有很多缺点,不仅麻烦,而且容易漏了组件启动,还会对后面动态组件扩展带来麻烦 ...

  2. System startup files

    System startup files When you log in, the shell defines your user environment after reading the init ...

  3. Oracle 执行计划(Explain Plan) 说明

    如果要分析某条SQL的性能问题,通常我们要先看SQL的执行计划,看看SQL的每一步执行是否存在问题. 如果一条SQL平时执行的好好的,却有一天突然性能很差,如果排除了系统资源和阻塞的原因,那么基本可以 ...

  4. Android View框架总结(七)View事件分发机制

    请尊重分享成果,转载请注明出处: http://blog.csdn.net/hejjunlin/article/details/52282833 View布局告一段落,从本篇开始View事件相关分析, ...

  5. TBschedule入门

    tbschedule 淘宝的wiki: http://code.taobao.org/p/tbschedule/wiki/index/ 截取内容如下: 此文档内部包括: 1.设计目标说明 2.主要概念 ...

  6. android开源库发布到jcenter图文详解与填坑

    相信很多人都用过开源项目,特别是android studio普及以后,使用开源库更方便简单.而如何上传开源库到jcenter供大家方便使用,虽然网上也有教程,但还是遇坑了,最后总结一下,希望可以帮助大 ...

  7. 05 Activity 现场保护

    我们接电话然后返回的 Activity将会被毁了重新创建 所以我们需要在摧毁记录一些信息还原Activity 摧毁时: //在Activi被摧毁的调用此方法 @Override protected v ...

  8. gradle测试出现IllegalArgumentException

    今天clone了一份代码,跑gradle test时出现failed,从report上来看是这个错误:IllegalArgumentException,具体如下: java.lang.IllegalA ...

  9. 手把手带你走进MVP +Dagger2 + DataBinding+ Rxjava+Retrofit 的世界

    0.0 Android开发现在的变化用一个词来形容就是 :翻天覆地 越来越多的项目使用了MVP + Rxjava+Retrofit +Dagger2 + DataBinding等等东西.. 但是这些东 ...

  10. 安卓中的事件分发机制之View控件

    前言:Android 中与 Touch 事件相关的方法包括:dispatchTouchEvent(MotionEvent ev).onInterceptTouchEvent(MotionEvent e ...