SparkSQL基于DataSourceV2自定义数据源

SparkSQL基于DataSourceV2自定义数据源
版本说明:Spark 2.3

前言:之前在SparkSQL数据源操作文章中整理了一些SparkSQL内置数据源的使用,总的来说SparkSQL支持的数据源还是挺丰富的,但业务上可能不拘束于这几种数据源,比如将HBase作为SparkSQL的数据源,REST数据源等。这里主要讲一下在Spark2.3版本之后推出的DataSourceV2,基于DataSourceV2实现自定义数据源

1 DataSourceV1 VS DataSourceV2
自Spark1.3版本之后,引入了数据源API,我们可以实现自定义数据源。2.3版本之后又引入的新版API,关于V1与V2的区别以及使用可以参考https://blog.csdn.net/zjerryj/article/details/84922369与https://developer.ibm.com/code/2018/04/16/introducing-apache-spark-data-sources-api-v2/这两篇文章。这里简单的总结一下V1的缺点,以及V2的新特性。

1.1 DataSourceV1缺点
依赖上层API
难以添加新的优化算子
难以传递分区信息
缺少事务性的写操作
缺少列存储和流式计算支持
1.2 DataSourceV2优点
DataSourceV2 API使用Java编写
不依赖于上层API(DataFrame/RDD)
易于扩展,可以添加新的优化,同时保持向后兼容
提供物理信息,如大小、分区等
支持Streamin Source/Sink
灵活、强大和事务性的写入API
1.3 Spark2.3中V2的功能
支持列扫描和行扫描
列裁剪和过滤条件下推
可以提供基本统计和数据分区
事务写入API
支持微批和连续的Streaming Source/Sink
2 基于DataSourceV2实现输入源
SparkSQL的DataSourceV2的实现与StructuredStreaming自定义数据源如出一辙,思想是一样的,但是具体实现有所不同,主要步骤如下:

第一步:继承DataSourceV2和ReadSupport创建XXXDataSource类,重写ReadSupport的creatReader方法,用来返回自定义的DataSourceReader类,如返回自定义XXXDataSourceReader实例

第二步:继承DataSourceReader创建XXXDataSourceReader类,重写DataSourceReader的readSchema方法用来返回数据源的schema,重写DataSourceReader的createDataReaderFactories用来返回多个自定义DataReaderFactory实例

第三步:继承DataReaderFactory创建DataReader工厂类,如XXXDataReaderFactory,重写DataReaderFactory的createDataReader方法,返回自定义DataRader实例

第四步:继承DataReader类创建自定义的DataReader,如XXXDataReader,重写DataReader的next()方法,用来告诉Spark是否有下条数据,用来触发get()方法,重写DataReader的get()方法获取数据,重写DataReader的close()方法用来关闭资源

2.1 继承DataSourceV2和ReadSupport创建XXXDataSource类
这里以创建CustomDataSourceV2类为例

2.1.1 创建CustomDataSourceV2类
/**
  * 创建DataSource提供类
  * 1.继承DataSourceV2向Spark注册数据源
  * 2.继承ReadSupport支持读数据
  */
class CustomDataSourceV2 extends DataSourceV2
  with ReadSupport {
      // todo
}
1
2
3
4
5
6
7
8
9
2.1.2 重写ReadSupport的createReader方法
该方法用来返回一个用户自定义的DataSourceReader实例

  /**
    * 创建Reader
    *
    * @param options 用户定义的options
    * @return 自定义的DataSourceReader
    */
  override def createReader(options: DataSourceOptions): DataSourceReader = new CustomDataSourceV2Reader(options)
1
2
3
4
5
6
7
2.2 继承DataSourceReader创建XXXDataSourceReader类
该类用来自定义DataSourceReader,需要继承DataSourceReader,并重写readSchema和createDataReaderFactories方法。

2.2.1 创建CustomDataSourceV2Reader类
/**
  * 自定义的DataSourceReader
  * 继承DataSourceReader
  * 重写readSchema方法用来生成schema
  * 重写createDataReaderFactories,用来根据条件,创建多个工厂实例
  *
  * @param options options
  */
class CustomDataSourceV2Reader(options: DataSourceOptions) extends DataSourceReader {
    // Override some functions
}
1
2
3
4
5
6
7
8
9
10
11
2.2.2 重写DataSourceReader的readSchema方法
该方法用来返回数据源的schema

/**
  * 生成schema
  *
  * @return schema
  */
override def readSchema(): StructType = ???
1
2
3
4
5
6
2.2.3 重写DataSourceReader的createDataReaderFactories方法
实现该方法,可以根据不同的条件,创建多个createDataReader工厂实例,用来并发获取数据?(暂且这么理解的,或者是按照分区获取数据?)

  /**
    * 创建DataReader工厂实例
    *
    * @return 多个工厂类实例
    */
  override def createDataReaderFactories(): util.List[DataReaderFactory[Row]] = {
    import collection.JavaConverters._
    Seq(
      new CustomDataSourceV2ReaderFactory().asInstanceOf[DataReaderFactory[Row]]
    ).asJava
  }
1
2
3
4
5
6
7
8
9
10
11
2.3 继承DataReaderFactory创建DataReader工厂类
该类是DataReader的工厂来,用来返回DataReader实例

2.3.1 创建CustomDataSourceV2Factory类
/**
  * 自定义DataReaderFactory类
  */
class CustomDataSourceV2ReaderFactory extends DataReaderFactory[Row] {
   // Override some functions
}

1
2
3
4
5
6
7
2.3.2 重写DataReaderFactory的createDataReader方法
该方法用来实例化自定义的DataReader

  /**
    * 重写createDataReader方法,用来实例化自定义的DataReader
    *
    * @return 自定义的DataReader
    */
  override def createDataReader(): DataReader[Row] = new CustomDataReader
1
2
3
4
5
6
2.4 继承DataReader类创建自定义的DataReader
该类为重点实现部分,用来自定义获取数据的方式

2.4.1 创建CustomDataReader类
/**
  * 自定义DataReader类
  */
class CustomDataReader extends DataReader[Row] {
    // Override some functions
}
1
2
3
4
5
6
2.4.2 重写CustomDataReader的next()方法
该方法返回一个布尔值,来告诉Spark是否含有下条数据,以便触发get()方法获取数据

  /**
    * 是否有下一条数据
    *
    * @return boolean
    */
  override def next(): Boolean = ???
1
2
3
4
5
6
2.4.3 重写CustomDataReader的get()方法
该方法用来获取数据,返回类型是在继承DataReader时指定的泛型

  /**
    * 获取数据
    * 当next为true时会调用get方法获取数据
    *
    * @return Row
    */
  override def get(): Row = ???
1
2
3
4
5
6
7
2.4.4 重写CustomDataReader的close()方法
该方法用来关闭相应的资源

  /**
    * 关闭资源
    */
  override def close(): Unit = ???
1
2
3
4
2.5 以REST为例,实现自定义的数据源
这里主要是从REST接口里获取JSON格式的数据,然后生成DataFrame数据源

2.5.1 创建RestDataSource类

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 配置SparkSQL数据 在DolphinScheduler的web管理页面中,点击左侧的“数据”菜单,然后点击“新增”按钮,在弹出的页面中选择“SparkSQL数据类型,填写相关配置信息,如下图所示: ![image.png](https://cdn.nlark.com/yuque/0/2022/png/215728/1644455710852-7e500e9c-7d03-453b-9d7e-17b1c7e8510d.png#clientId=u7f8b614c-2d08-4&from=paste&id=ua1e4f4e4&margin=%5Bobject%20Object%5D&originHeight=1184&originWidth=2542&originalType=binary&ratio=1&status=done&style=none&taskId=u6d5f7a55-6a8e-4dcd-9d3a-3a6f4b6a4b6) 其中,配置信息的具体含义如下: - 数据名称:自定义数据的名称,例如“SparkSQL”; - 数据类型:选择“SparkSQL”; - JDBC URL:填写SparkSQL连接的JDBC URL,例如“jdbc:spark://localhost:7077”; - 用户名:填写SparkSQL连接的用户名,例如“root”; - 密码:填写SparkSQL连接的密码,例如“123456”。 2. 测试SparkSQL数据 配置完成后,点击“测试连接”按钮,测试数据是否能够连接成功。如果连接成功,则会出现“连接成功”的提示信息;如果连接失败,则会出现“连接失败”的提示信息。 3. 在任务中使用SparkSQL数据 在DolphinScheduler的web管理页面中,点击左侧的“任务”菜单,然后点击“新增”按钮,在弹出的页面中选择要创建的任务类型(例如“SQL”任务),然后填写任务相关信息,如下图所示: ![image.png](https://cdn.nlark.com/yuque/0/2022/png/215728/1644455731711-6558c0b9-7a63-4f1f-aa8a-08e2d63c94f6.png#clientId=u7f8b614c-2d08-4&from=paste&id=udbcb1c3d&margin=%5Bobject%20Object%5D&originHeight=1184&originWidth=2542&originalType=binary&ratio=1&status=done&style=none&taskId=u9f7a46d1-1f7a-4aa2-8d45-71e84d7c1a9) 其中,配置信息的具体含义如下: - 任务名称:自定义任务的名称,例如“SparkSQL任务”; - 任务类型:选择要创建的任务类型,例如“SQL”任务; - 数据类型:选择“SparkSQL”; - SQL语句:填写要执行的SQL语句,例如“select * from table”; - 运行参数:填写任务的运行参数,例如“--executor-memory 512m”。 配置完成后,点击“保存”按钮,保存任务信息。然后,点击“运行”按钮,运行任务。如果任务能够正常运行,则会出现“运行成功”的提示信息;如果任务运行失败,则会出现“运行失败”的提示信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值