spark的bulkload报错及解决
需求
将HDFS上的数据解析出来,然后通过hfile方式批量写入Hbase(需要多列写入)
写入数据的关键api:
- rdd.saveAsNewAPIHadoopFile(
- stagingFolder,
- classOf[ImmutableBytesWritable],
- classOf[KeyValue],
- classOf[HFileOutputFormat2],
- job.getConfiguration)
特殊地方:
1):
最初写hfile警告⚠️:
- Does it contain files in subdirectories that correspond to column family names
这个原因大概3种:
A:代码问题
B:数据源问题
C:setMapOutputKeyClass 和 saveAsNewAPIHadoopFile中的Class不一致
(我的是数据源问题)
2):
正常些put操作的时候,服务端自动帮助排序,因此在使用put操作的时候没有涉及到这样的错误:
- Added a key not lexically larger than previous
但是在写hfile的时候如果出现报错:
- Added a key not lexically larger than previous
这样的错误,一般会认为rowkey没有做好排序,然后傻fufu的去验证了一下,rowkey的确做了排序
真正原因:
spark写hfile时候是按照rowkey+列族+列名进行排序的,因此在写入数据的时候,要做到整体有序
(事情还没完)
3):
因为需要多列写入,最好的方式:要么反射来动态获取列名称和列值 、 要么通过datafame去获取(df.columns)
反射方式:
- val listData: RDD[(ImmutableBytesWritable, ListBuffer[KeyValue])] = rdd.map {
- line =>
- val rowkey = line.vintime
- val clazz = Class.forName(XXXXXXXXXXXXXXXX)
- val fields = clazz.getDeclaredFields
- var list = new ListBuffer[String]()
- var kvlist = new ListBuffer[KeyValue]()//
- if (fields != null && fields.size > ) {
- for (field <- fields) {
- field.setAccessible(true)
- val column = field.getName
- list.append(column)
- }
- }
- val newList = list.sortWith(_ < _)
- val ik = new ImmutableBytesWritable(Bytes.toBytes(rowkey))
- for(column <- newList){
- val declaredField: Field = line.getClass.getDeclaredField(column)
- declaredField.setAccessible(true)
- val value = declaredField.get(line).toString
- val kv: KeyValue = new KeyValue(
- Bytes.toBytes(rowkey),
- Bytes.toBytes(columnFamily),
- Bytes.toBytes(column),
- Bytes.toBytes(value))
- kvlist.append(kv)
- }
- (ik, kvlist)
- }
datafame方式:
- val tmpData: RDD[(ImmutableBytesWritable, util.LinkedList[KeyValue])] = df.rdd.map(
- line =>{
- val rowkey = line.getAs[String]("vintime")
- val ik = new ImmutableBytesWritable(Bytes.toBytes(rowkey))
- var linkedList = new util.LinkedList[KeyValue]()
- for (column <- columns) {
- val kv: KeyValue = new KeyValue(
- Bytes.toBytes(rowkey),
- Bytes.toBytes(columnFamily),
- Bytes.toBytes(column),
- Bytes.toBytes(line.getAs[String](column)))
- linkedList.add(kv)
- }
- (ik, linkedList)
- })
- val result: RDD[(ImmutableBytesWritable, KeyValue)] = tmpData.flatMapValues(
- s => {
- val values: Iterator[KeyValue] = JavaConverters.asScalaIteratorConverter(s.iterator()).asScala
- values
- }
- ).sortBy(x =>x._1 , true)
仔细观察可以发现,其实两者都做了排序操作,但是即便经过(1)步骤后仍然报错:
- Added a key not lexically larger than previous
那么在回想一下之前写hfile的要求:
rowkey+列族+列都要有序,那么如果出现数据的重复,也不算是有序的操作!
因为,做一下数据的去重:
- val key: RDD[(String, TransferTime)] = data.reduceByKey((x, y) => y)
- val unitData: RDD[TransferTime] = key.map(line => line._2)
果然,这样解决了:Added a key not lexically larger than previous这个异常
但是会报如下另一个异常:
- Kryo serialization failed: Buffer overflow
这个是因为在对一些类做kryo序列化时候,数据量的缓存大小超过了默认值,做一下调整即可
- sparkConf.set("spark.kryoserializer.buffer.max" , "256m")
- sparkConf.set("spark.kryoserializer.buffer" , "64m")
完整代码:
- /**
- * Created by angel
- */
- object WriteTransferTime extends WriteToHbase{
- /**
- * @param data 要插入的数据
- * @param tableName 表名
- **/
- override def bulkLoadData(data: RDD[Any], tableName: String , columnFamily:String): Unit = {
- val bean: RDD[TransferTime] = data.map(line => line.asInstanceOf[TransferTime])
- val map: RDD[(String, TransferTime)] = bean.map(line => (line.vintime , line))
- val key: RDD[(String, TransferTime)] = map.reduceByKey((x, y) => y)
- val map1: RDD[TransferTime] = key.map(line => line._2)
- val by1: RDD[TransferTime] = map1.sortBy(f => f.vintime)
- val listData: RDD[(ImmutableBytesWritable, ListBuffer[KeyValue])] = by1.map {
- line =>
- val rowkey = line.vintime
- val clazz = Class.forName("com.dongfeng.code.Bean.message.TransferTime")
- val fields = clazz.getDeclaredFields
- var list = new ListBuffer[String]()
- var kvlist = new ListBuffer[KeyValue]()//
- if (fields != null && fields.size > 0) {
- for (field <- fields) {
- field.setAccessible(true)
- val column = field.getName
- list.append(column)
- }
- }
- val newList = list.sortWith(_ < _)
- val ik = new ImmutableBytesWritable(Bytes.toBytes(rowkey))
- for(column <- newList){
- val declaredField: Field = line.getClass.getDeclaredField(column)
- declaredField.setAccessible(true)
- val value = declaredField.get(line).toString
- val kv: KeyValue = new KeyValue(
- Bytes.toBytes(rowkey),
- Bytes.toBytes(columnFamily),
- Bytes.toBytes(column),
- Bytes.toBytes(value))
- kvlist.append(kv)
- }
- (ik, kvlist)
- }
- val result: RDD[(ImmutableBytesWritable, KeyValue)] = listData.flatMapValues(
- s => {
- val values: Iterator[KeyValue] = s.iterator
- values
- }
- )
- val resultDD: RDD[(ImmutableBytesWritable, KeyValue)] = result.sortBy(x =>x._1 , true)
- WriteToHbaseDB.hfile_load(result , TableName.valueOf(tableName) , columnFamily)
- }
- }
WriteTransferTime
- def hfile_load(rdd:RDD[(ImmutableBytesWritable , KeyValue)] , tableName: TableName , columnFamily:String): Unit ={
- //声明表的信息
- var table: Table = null
- try{
- val startTime = System.currentTimeMillis()
- println(s"开始时间:-------->${startTime}")
- //生成的HFile的临时保存路径
- val stagingFolder = "hdfs://cdh1:9000/hfile/"+tableName+new Date().getTime//
- table = connection.getTable(tableName)
- //如果表不存在,则创建表
- if(!admin.tableExists(tableName)){
- createTable(tableName , columnFamily)
- }
- //开始导入
- val job = Job.getInstance(config)
- job.setJobName("DumpFile")
- job.setMapOutputKeyClass(classOf[ImmutableBytesWritable])
- job.setMapOutputValueClass(classOf[KeyValue])
- rdd.sortBy(x => x._1, true).saveAsNewAPIHadoopFile(
- stagingFolder,
- classOf[ImmutableBytesWritable],
- classOf[KeyValue],
- classOf[HFileOutputFormat2],
- job.getConfiguration)
- val load = new LoadIncrementalHFiles(config)
- val regionLocator = connection.getRegionLocator(tableName)
- HFileOutputFormat2.configureIncrementalLoad(job, table, regionLocator)
- load.doBulkLoad(new Path(stagingFolder), table.asInstanceOf[HTable])
- // load.doBulkLoad(new Path(stagingFolder) , connection.getAdmin , table , regionLocator)
- val endTime = System.currentTimeMillis()
- println(s"结束时间:-------->${endTime}")
- println(s"花费的时间:----------------->${(endTime - startTime)}ms")
- }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的bulkload报错及解决的更多相关文章
- Spark遇到的报错和坑
1. Java版本不一致,导致启动报错. # 解决方法: 在启动脚本最前边添加系统参数,指定Java版本 export JAVA_HOME=/usr/java/jdk1..0_181-amd64/jr ...
- Spark程序编译报错error: object apache is not a member of package org
Spark程序编译报错: [INFO] Compiling 2 source files to E:\Develop\IDEAWorkspace\spark\target\classes at 156 ...
- Springboot数据库连接池报错的解决办法
Springboot数据库连接池报错的解决办法 这个异常通常在Linux服务器上会发生,原因是Linux系统会主动断开一个长时间没有通信的连接 那么我们的问题就是:数据库连接池长时间处于间歇状态,导致 ...
- window7下安装第三方包报错及解决
window7 64位下安装第三方包,,比如安装yaml的exe执行文件,会 报错及解决:python version 2.7(3.4) required,which was not found in ...
- pom.xml里有红叉报错的解决办法
pom.xml里有红叉报错的解决办法一: 1.把鼠标点在报的错上发现pom.xml报如下错误: Multiple annotations found at this line: - Failure t ...
- eclipes的Spring注解SequenceGenerator(name="sequenceGenerator")报错的解决方式
eclipes的Spring注解SequenceGenerator(name="sequenceGenerator")报错的解决方式 右键项目打开Properties—>JA ...
- Can't bind to local 8700 for debugger报错和解决
[2016-02-15 22:37:17 - ddms] Can't bind to local 8700 for debugger报错和解决 1.打开studio monitor是出错: Can't ...
- Loadrunner参数化连接oracle、mysql数据源报错及解决办法
Loadrunner参数化连接oracle.mysql数据源报错及解决办法 (本人系统是Win7 64, 两位小伙伴因为是默认安装lr,安装在 最终参数化的时候,出现连接字符串无法自动加载出来: 最 ...
- ArcGIS API for Silverlight 调用WebService出现跨域访问报错的解决方法
原文:ArcGIS API for Silverlight 调用WebService出现跨域访问报错的解决方法 群里好几个朋友都提到过这样的问题,说他们在Silverlight中调用了WebServi ...
随机推荐
- docker的安装,升级,与删除(最新版)
docker安装在ubuntu上 以前叫做 Docker engine安装现在叫做docker-ce的 第一种安装办法: root下执行,sudo su - root apt-get update - ...
- 爬虫 requests 模块
requests 模块 介绍 使用requests可以模拟浏览器的请求, 比起之前用到的urllib,requests模块的api更加便捷(本质就是封装了urllib3) ps: requests库发 ...
- centos6/7安装java和maven
下载安装包并解压到相关目录即可 编辑环境变量vim /etc/profile.d/maven.sh export JAVA_HOME=/app/soft/java-1.8.0_181 export J ...
- 洛谷P5289 皮配
解:观察一波部分分. 首先小数据直接暴力4n,然后考虑背包.设f[i][a][b][c]表示前i个学校中前三位导师分别有多少人,第四位导师可以直接推出来. 然后暴力枚举每一个人放在哪进行背包. 进一步 ...
- 简单的实现HTTP密码验证登陆
1.首先需要安装 httpd-tools yum install -y httpd-tools 2.安装完成后设置用户名密码,我这里用的是NGINX htpasswd -bc /mypath/ngin ...
- bootstrap学习: 折叠插件和面板
bootstrap提供了面板排版工具和折叠插件,能够用来实现新闻列表.留言板.博客分块等: 1.折叠插件: <a data-toggle="collapse" data-ta ...
- 剑指Offer_编程题_19
题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2, ...
- Pandas系列(四)-文本数据处理
内容目录 1. 为什么要用str属性 2. 替换和分割 3. 提取子串 3.1 提取第一个匹配的子串 3.2 匹配所有子串 3.3 测试是否包含子串 3.4 生成哑变量 3.5 方法摘要 一.为什么要 ...
- Git Gerrit使用
Git Gerrit 操作都用 git bash操作: 如果想用 cmd 或者 PowerShell,系统环境变量 Path 添加 Git 安装路径,如: C:\Program Files (x86) ...
- 第十二节:Lambda、linq、SQL的相爱相杀(1)
一. 谈情怀 Lambda.Linq.SQL伴随着我的开发一年又一年,但它们三者并没有此消彼长,各自占有这一定的比重,起着不可替代的作用. 相信我们最先接触的应该就是SQL了,凡是科班出身的人,大学 ...