由于SparkSQL不支持HBase的数据源(HBase-1.1.2),网上有很多是采用Hortonworks的SHC,而SparkSQL操作HBase自定义数据源大多数都是基于Scala实现,我就自己写了一个Java版的SparkSQL操作HBase的小案例。

1、SparkOnHBase

package com.mengyao.tag.utils.external.hbase;

import org.apache.spark.SparkConf;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.SparkSession; /**
*
* @author mengyao
*
*/
public class SparkSQLOnHBase { public static void main(String[] args) {
SparkConf conf = new SparkConf()
.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer"); SparkSession session = SparkSession.builder()
.config(conf)
.appName("SparkOnHBase")
.master("local[*]")
.getOrCreate(); Dataset<Row> df = session.read()
.format("com.mengyao.tag.utils.external.hbase.HBaseSource")
.option("zkHosts", "192.168.10.20")
.option("zkPort", "2181")
.option("hbaseTable", "tbl_tag_user")
.option("family", "test")
.option("selectFields", "id,username,email,phone")
//.option("selectFields", "uid,tids")
.load();
df.printSchema();
df.logicalPlan();
df.explain();
df.filter("id>10").show(); session.close();
} }

2、HBaseSource

package com.mengyao.tag.utils.external.hbase;

import org.apache.spark.sql.SQLContext;
import org.apache.spark.sql.sources.BaseRelation;
import org.apache.spark.sql.sources.RelationProvider; import scala.collection.immutable.Map; /**
*
* @author mengyao
*
*/
public class HBaseSource implements RelationProvider {
@Override
public BaseRelation createRelation(SQLContext sqlContext, Map<String, String> options) {
return new HBaseRelation(sqlContext, options);
}
}

3、HBaseRelation

package com.mengyao.tag.utils.external.hbase;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Stream; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.TableInputFormat;
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.protobuf.generated.ClientProtos;
import org.apache.hadoop.hbase.util.Base64;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.spark.rdd.RDD;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.RowFactory;
import org.apache.spark.sql.SQLContext;
import org.apache.spark.sql.sources.BaseRelation;
import org.apache.spark.sql.sources.TableScan;
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.StructField;
import org.apache.spark.sql.types.StructType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import com.google.common.base.Preconditions; import scala.Tuple2;
import scala.collection.JavaConverters;
import scala.collection.immutable.Map; /**
*
* @author mengyao
*
*/
public class HBaseRelation extends BaseRelation implements Serializable, TableScan {
private static final long serialVersionUID = 4234614443074355432L;
private static transient Logger logger = LoggerFactory.getLogger(HBaseRelation.class);
private final String HBASE_ZK_PORT_KEY = "hbase.zookeeper.property.clientPort";
private final String HBASE_ZK_PORT_VALUE = "zkPort";
private final String HBASE_ZK_QUORUM_KEY = "hbase.zookeeper.quorum";
private final String HBASE_ZK_QUORUM_VALUE = "zkHosts";
private final String HBASE_ZK_PARENT_KEY = "zookeeper.znode.parent";
private final String HBASE_ZK_PARENT_VALUE = "/hbase-unsecure";
private final String HBASE_TABLE = "hbaseTable";
private final String HBASE_TABLE_FAMILY = "family";
private final String HBASE_TABLE_SELECT_FIELDS = "selectFields";
private final String sperator = ",";
private final String ROW = "row";
private SQLContext sqlContext;
private java.util.Map<String, String> options;
private StructType schema = null;
private boolean updateSchema = true; public HBaseRelation(SQLContext sqlContext, Map<String, String> options) {
this.sqlContext = sqlContext;
this.options = JavaConverters.mapAsJavaMapConverter(options).asJava();
} @Override
public RDD<Row> buildScan() {
validParams(options);
return scan(sqlContext, options);
} @Override
public StructType schema() {
if (updateSchema || schema == null) {
List<StructField> fields = new ArrayList<>();
fields.add(DataTypes.createStructField(ROW, DataTypes.StringType, false));
String fieldsStr = options.get(HBASE_TABLE_SELECT_FIELDS);
String[] fieldStrs = fieldsStr.split(sperator);
Stream.of(fieldStrs).forEach(field -> fields.add(DataTypes.createStructField(field, DataTypes.StringType, false)));
schema = DataTypes.createStructType(fields);
updateSchema = false;
}
logger.info("==== HBaseSource Schema is:{} ====", schema);
return schema;
} @Override
public SQLContext sqlContext() {
return sqlContext;
} private void validParams(java.util.Map<String, String> options){
String zkHosts = options.get(HBASE_ZK_QUORUM_VALUE);
Preconditions.checkNotNull(zkHosts, "zkHosts not null!");
String zkPort = options.get(HBASE_ZK_PORT_VALUE);
Preconditions.checkNotNull(zkPort, "zkPort not null!");
String family = options.get(HBASE_TABLE_FAMILY);
Preconditions.checkNotNull(family, "family not null!");
String fieldsStr = options.get(HBASE_TABLE_SELECT_FIELDS);
Preconditions.checkNotNull(fieldsStr, "fieldsStr not null!");
} private RDD<Row> scan(SQLContext sqlContext, java.util.Map<String, String> options) {
try {
Configuration conf = HBaseConfiguration.create();
conf.set(HBASE_ZK_PORT_KEY, options.get(HBASE_ZK_PORT_VALUE));
conf.set(HBASE_ZK_QUORUM_KEY, options.get(HBASE_ZK_QUORUM_VALUE));
conf.set(HBASE_ZK_PARENT_KEY, HBASE_ZK_PARENT_VALUE);
String family = options.get(HBASE_TABLE_FAMILY);
String fieldsStr = options.get(HBASE_TABLE_SELECT_FIELDS);
String[] selectFileds = fieldsStr.split(sperator); Scan scan = new Scan();
conf.set(TableInputFormat.INPUT_TABLE, options.get(HBASE_TABLE));
ClientProtos.Scan proto = ProtobufUtil.toScan(scan);
String scanStr = Base64.encodeBytes(proto.toByteArray());
conf.set(TableInputFormat.SCAN, scanStr);
logger.info("==== HBaseSource Scan is:{} ====", scanStr); RDD<Tuple2<ImmutableBytesWritable, Result>> hbaseRdd = sqlContext.sparkContext().newAPIHadoopRDD(conf,
TableInputFormat.class, ImmutableBytesWritable.class, Result.class); return hbaseRdd.toJavaRDD().map(t -> t._2).map(r -> {
LinkedList<String> vals = new LinkedList<>();
String row = Bytes.toString(r.getRow());
vals.add(row);
Stream.of(selectFileds).forEach(field -> {
String val = Bytes.toString(r.getValue(Bytes.toBytes(family), Bytes.toBytes(field)));
vals.add(val);
});
return (Row) RowFactory.create(vals.toArray());
}).rdd();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

Spark-2.3.2 Java SparkSQL的自定义HBase数据源的更多相关文章

  1. SparkSQL 如何自定义函数

    1. SparkSql如何自定义函数 2. 示例:Average 3. 类型安全的自定义函数 1. SparkSql如何自定义函数? spark中我们定义一个函数,需要继承 UserDefinedAg ...

  2. spark提示Caused by: java.lang.ClassCastException: scala.collection.mutable.WrappedArray$ofRef cannot be cast to [Lscala.collection.immutable.Map;

    spark提示Caused by: java.lang.ClassCastException: scala.collection.mutable.WrappedArray$ofRef cannot b ...

  3. [转]Java中实现自定义的注解处理器

    Java中实现自定义的注解处理器(Annotation Processor) 置顶2016年07月25日 19:42:49 阅读数:9877 在之前的<简单实现ButterKnife的注解功能& ...

  4. 移动开发首页业界资讯移动应用平台技术专题 输入您要搜索的内容 基于Java Socket的自定义协议,实现Android与服务器的长连接(二)

    在阅读本文前需要对socket以及自定义协议有一个基本的了解,可以先查看上一篇文章<基于Java Socket的自定义协议,实现Android与服务器的长连接(一)>学习相关的基础知识点. ...

  5. spark 执行报错 java.io.EOFException: Premature EOF from inputStream

    使用spark2.4跟spark2.3 做替代公司现有的hive选项. 跑个别任务spark有以下错误 java.io.EOFException: Premature EOF from inputSt ...

  6. Java之SpringBoot自定义配置与整合Druid

    Java之SpringBoot自定义配置与整合Druid SpringBoot配置文件 优先级 前面SpringBoot基础有提到,关于SpringBoot配置文件可以是properties或者是ya ...

  7. 《手把手教你》系列技巧篇(七十一)-java+ selenium自动化测试-自定义类解决元素同步问题(详解教程)

    1.简介 前面宏哥介绍了几种关于时间等待的方法,也提到了,在实际自动化测试脚本开发过程,百分之90的报错是和元素因为时间不同步而发生报错.本文介绍如何新建一个自定义的类库来解决这个元素同步问题.这样, ...

  8. 0基础就可以上手的Spark脚本开发-for Java

    前言 最近由于工作需要,要分析大几百G的Nginx日志数据.之前也有过类似的需求,但那个时候数据量不多.一次只有几百兆,或者几个G.因为数据都在Hive里面,当时的做法是:把数据从Hive导到MySQ ...

  9. 第十一篇:Spark SQL 源码分析之 External DataSource外部数据源

    上周Spark1.2刚发布,周末在家没事,把这个特性给了解一下,顺便分析下源码,看一看这个特性是如何设计及实现的. /** Spark SQL源码分析系列文章*/ (Ps: External Data ...

随机推荐

  1. 【电商日志项目之四】数据清洗-ETL

    环境 hadoop-2.6.5 首先要知道为什么要做数据清洗?通过各个渠道收集到的数据并不能直接用于下一步的分析,所以需要对这些数据进行缺失值清洗.格式内容清洗.逻辑错误清洗.非需求数据清洗.关联性验 ...

  2. 算法练习之合并两个有序链表, 删除排序数组中的重复项,移除元素,实现strStr(),搜索插入位置,无重复字符的最长子串

    最近在学习java,但是对于数据操作那部分还是不熟悉 因此决定找几个简单的算法写,用php和java分别实现 1.合并两个有序链表 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两 ...

  3. 【视频开发】关于FFMPEG中内存泄漏的问题之av_bitstream_filter_filter

    How may I free pkt in an ffmpeg write frame method Rate this:      See more: C++ ffmpeg Greetings I' ...

  4. 【计算机视觉】目标检测中的指标衡量Recall与Precision

    [计算机视觉]目标检测中的指标衡量Recall与Precision 标签(空格分隔): [图像处理] 说明:目标检测性能指标Recall与Precision的理解. Recall与Precision ...

  5. djngo未整理

    Django Django基础命令 - runserver 本地建议运行Django - shell 进入Django项目得python shell环境 - test 执行Django 用列测试 数据 ...

  6. 常用Tables控件介绍(二)

    初始化:1.使用现有表单创建数据表格,定义在HTML中的字段和数据 2.使用现有的table创建数据表格,定义在HTML中的字段 3.使用JS创建数据库表格 一.初始化后,根据单元格内的值,修改显示内 ...

  7. 5. RDD编程进阶

    5.1 累加器 累加器用来对信息进行聚合,通常在向Spark传递函数时,比如使用map()函数或者用filter()传条件时,可以使用驱动器程序中定义的变量,但是集群中运行的每个任务都会得到这些变量的 ...

  8. R学习笔记3 数据处理

    1,日期类型 日期类型比较特殊,日期值通常以字符串的形式输入到R中,然后使用as.Date()函数转换为以数值形式存储的日期变量 mydate <- as.Date("2019-01- ...

  9. LOJ3146 APIO2019路灯(cdq分治+树状数组)

    每个时刻都形成若干段满足段内任意两点可达.将其视为若干正方形.则查询相当于求历史上某点被正方形包含的时刻数量.并且注意到每个时刻只有O(1)个正方形出现或消失,那么求出每个矩形的出现时间和消失时间,就 ...

  10. React 了解学习

    1.nodejs安装程序https://nodejs.org/en/download/ create-react-app 类似 vs2017开发工具,集成了webpack 打包发布,loader和默认 ...