1:为什么大批量数据集写入Hbase中,需要使用bulkload

  • BulkLoad不会写WAL,也不会产生flush以及split。
  • 如果我们大量调用PUT接口插入数据,可能会导致大量的GC操作。除了影响性能之外,严重时甚至可能会对HBase节点的稳定性造成影响。但是采用BulkLoad就不会有这个顾虑。
  • 过程中没有大量的接口调用消耗性能
  • 可以利用spark 强大的计算能力

上面是一个总的执行流程图, 数据生成,HFile转换以及HFile加载, 下面是HFile 的格式, 就是个key value 存储结构,
key 是由行健column family 和限定符指定, 然后再加上key的索引

注意:

生成HFile要求Key有序。开始是以为只要行键有序,即map之后,sortByKey就ok,后来HFileOutputFormat一直报后值比前值小(即未排序)。翻了很多鬼佬网站,才发现,这里的行键有序,是要求rowKey+列族+列名整体有序!!!

package hbaseLoad.CommonLoad

import java.io.IOException
import java.sql.Date
import java.util
import java.util.concurrent.{Executors, ScheduledExecutorService, TimeUnit} import org.apache.hadoop.fs.Path
import org.apache.hadoop.hbase.client._
import org.apache.hadoop.hbase.io.ImmutableBytesWritable
import org.apache.hadoop.hbase.mapreduce.{HFileOutputFormat2, LoadIncrementalHFiles}
import org.apache.hadoop.hbase.{HBaseConfiguration, HColumnDescriptor, HTableDescriptor, KeyValue, TableName}
import org.apache.hadoop.hbase.util.Bytes
import org.apache.hadoop.mapreduce.Job
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext} /**
* Created by angel;
*/
object Hfile {
val zkCluster = "hadoop01,hadoop02,hadoop03"
val hbasePort = "2181"
val tableName = TableName.valueOf("hfile")
val columnFamily = Bytes.toBytes("info")
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("Hfile").setMaster("local[*]")
conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer");
conf.registerKryoClasses(Array(classOf[D_class]))
val sc = new SparkContext(conf)
val fileData: RDD[String] = sc.textFile("data")
val rdd = fileData.map{
line =>
val dataArray = line.split("@")
val rowkey = dataArray(0)+dataArray(1)
val ik = new ImmutableBytesWritable(Bytes.toBytes(rowkey))
val kv = new KeyValue(Bytes.toBytes(rowkey) , columnFamily , Bytes.toBytes("info") , Bytes.toBytes(dataArray(2)+":"+dataArray(3)+":"+dataArray(4)+":"+dataArray(5)))
(ik , kv)
}
// val scheduledThreadPool = Executors.newScheduledThreadPool(4);
// scheduledThreadPool.scheduleWithFixedDelay(new Runnable() {
// override def run(): Unit = {
// println("=====================================")
// }
//
// }, 1, 3, TimeUnit.SECONDS);
hfile_load(rdd)
}
def hfile_load(rdd:RDD[Tuple2[ImmutableBytesWritable , KeyValue]]): Unit ={
val hconf = HBaseConfiguration.create()
hconf.set("hbase.zookeeper.quorum", zkCluster);
hconf.set("hbase.master", "hadoop01:60000");
hconf.set("hbase.zookeeper.property.clientPort", hbasePort);
hconf.setInt("hbase.rpc.timeout", 20000);
hconf.setInt("hbase.client.operation.timeout", 30000);
hconf.setInt("hbase.client.scanner.timeout.period", 200000);
//声明表的信息
var table: Table = null
var connection: Connection = null
try{
val startTime = System.currentTimeMillis()
println(s"开始时间:-------->${startTime}")
//生成的HFile的临时保存路径
val stagingFolder = "hdfs://hadoop01:9000/hfile"
//将日志保存到指定目录
rdd.saveAsNewAPIHadoopFile(stagingFolder,
classOf[ImmutableBytesWritable],
classOf[KeyValue],
classOf[HFileOutputFormat2],
hconf)
//开始即那个HFile导入到Hbase,此处都是hbase的api操作
val load = new LoadIncrementalHFiles(hconf) //创建hbase的链接,利用默认的配置文件,实际上读取的hbase的master地址
connection = ConnectionFactory.createConnection(hconf)
//根据表名获取表
table = connection.getTable(tableName)
val admin = connection.getAdmin
//构造表描述器
val hTableDescriptor = new HTableDescriptor(tableName)
//构造列族描述器
val hColumnDescriptor = new HColumnDescriptor(columnFamily)
hTableDescriptor.addFamily(hColumnDescriptor)
//如果表不存在,则创建表
if(!admin.tableExists(tableName)){
admin.createTable(hTableDescriptor)
}
//获取hbase表的region分布
val regionLocator = connection.getRegionLocator(tableName)
//创建一个hadoop的mapreduce的job
val job = Job.getInstance(hconf)
//设置job名称
job.setJobName("DumpFile")
//此处最重要,需要设置文件输出的key,因为我们要生成HFile,所以outkey要用ImmutableBytesWritable
job.setMapOutputKeyClass(classOf[ImmutableBytesWritable])
//输出文件的内容KeyValue
job.setMapOutputValueClass(classOf[KeyValue])
//配置HFileOutputFormat2的信息
HFileOutputFormat2.configureIncrementalLoad(job, table, regionLocator)
//开始导入
load.doBulkLoad(new Path(stagingFolder), table.asInstanceOf[HTable])
val endTime = System.currentTimeMillis()
println(s"结束时间:-------->${endTime}")
println(s"花费的时间:----------------->${(endTime - startTime)}")
}catch{
case e:IOException =>
e.printStackTrace()
}finally {
if (table != null) {
try {
// 关闭HTable对象 table.close();
} catch {
case e: IOException =>
e.printStackTrace();
}
}
if (connection != null) {
try { //关闭hbase连接. connection.close();
} catch {
case e: IOException =>
e.printStackTrace();
}
}
} } }

spark批量写写数据到Hbase中(bulkload方式)的更多相关文章

  1. java实现服务端守护进程来监听客户端通过上传json文件写数据到hbase中

    1.项目介绍: 由于大数据部门涉及到其他部门将数据传到数据中心,大部分公司采用的方式是用json文件的方式传输,因此就需要编写服务端和客户端的小程序了.而我主要实现服务端的代码,也有相应的客户端的测试 ...

  2. 简单通过java的socket&serversocket以及多线程技术实现多客户端的数据的传输,并将数据写入hbase中

    业务需求说明,由于公司数据中心处于刚开始部署的阶段,这需要涉及其它部分将数据全部汇总到数据中心,这实现的方式是同上传json文件,通过采用socket&serversocket实现传输. 其中 ...

  3. 【转载】C#批量插入数据到Sqlserver中的三种方式

    引用:https://m.jb51.net/show/99543 这篇文章主要为大家详细介绍了C#批量插入数据到Sqlserver中的三种方式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 本篇, ...

  4. 大数据学习day20-----spark03-----RDD编程实战案例(1 计算订单分类成交金额,2 将订单信息关联分类信息,并将这些数据存入Hbase中,3 使用Spark读取日志文件,根据Ip地址,查询地址对应的位置信息

    1 RDD编程实战案例一 数据样例 字段说明: 其中cid中1代表手机,2代表家具,3代表服装 1.1 计算订单分类成交金额 需求:在给定的订单数据,根据订单的分类ID进行聚合,然后管理订单分类名称, ...

  5. 批量导入数据到HBase

    hbase一般用于大数据的批量分析,所以在很多情况下需要将大量数据从外部导入到hbase中,hbase提供了一种导入数据的方式,主要用于批量导入大量数据,即importtsv工具,用法如下:   Us ...

  6. C#批量插入数据到Sqlserver中的四种方式

    我的新书ASP.NET MVC企业级实战预计明年2月份出版,感谢大家关注! 本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的 ...

  7. C#批量插入数据到Sqlserver中的三种方式

    本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生 成 ...

  8. C#_批量插入数据到Sqlserver中的四种方式

    先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生成一个GUID算法所花的时间肯定比你从数据表中重新查询上一条记 ...

  9. java批量插入数据进数据库中

    方式1: for循环,每一次进行一次插入数据. 方式2: jdbc的preparedStatement的batch操作 PreparedStatement.addBatch(); ...... Pre ...

随机推荐

  1. 获取日期Date

    获取特定时间戳: new Date("2018-06-12").getTime()   processDate(){ return { disabledDate(time){ re ...

  2. HDU 5288 OO’s Sequence

    题意: 给你一个序列, 有一个函数 F(L,R) 其中 ai 均不能 被 aL - aR整除的  函数值是这个ai个数 思路 : 反过来求 满足这样的条件的 ai 的区间,然后求和 #include& ...

  3. 17)django-模板的继承与导入

    情况1:通常写页面都有个模板用来框定头部LOGO页面,左侧导航菜单,只有右部的内容不同.如果不使用模板就大量重复工作. 特别如果头部或者左侧导航需要修改或者添加,所有页面都需要修改.django 通过 ...

  4. Android存储路径你了解多少?

    在了解存储路径之前,先来看看Android QQ的文件管理界面,了解一下QQ的数据文件路径来源,到底是来源于什么地方? 手Q文件管理对应存储目录 我的文件:是指放在QQ指定目录下的文件:/tencen ...

  5. 洛谷P4841 城市规划 [生成函数,NTT]

    传送门 题意简述:求\(n​\)个点的简单无向连通图的数量\(\mod \;1004535809​\),\(n \leq 130000​\) 经典好题呀!这里介绍两种做法:多项式求逆.多项式求对数 先 ...

  6. C#中lock死锁实例教程

    这篇文章主要介绍了C#中lock死锁的用法,对于共享资源的访问及C#程序设计的安全性而言,有着非常重要的意义!需要的朋友可以参考下 链接:http://www.jb51.net/article/543 ...

  7. Java学习——面向对象【3】

    1. 继承  java的类是单继承(一个子类只能继承一个父类),不能多继承(多个父类):A继承自B,A也继承自C,可以多重继承,就是A继承自B,B继承自C(A->B->C), 所有的类都继 ...

  8. Java感情

    不知道怎么会执着于这一门语言.论速度的话,c那系更好一些,而且对底层的操控更多是c那边的.还是想通过Java做这些事. 对Java不怎么懂,它的底层实现是怎样的.只知道一个大体的思想,不知道具体步骤. ...

  9. java.lang.NumberFormatException 错误及解决办法

    package com.geelou.test; public class ErrTest { public static void main(String[] args) { String numS ...

  10. Python查找最新测试报告到邮件功能

    #coding=utf-8 import smtplib from email.mime.text import MIMEText import unittest import HTMLTestRun ...