Spark(二十一)【SparkSQL读取Kudu,写入Kafka】
SparkSQL读取Kudu,写出到Kafka
背景:通过spark SQL读kudu表,写入到kafka
1. pom.xml 依赖
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
<!-- scalikejdbc_2.11 -->
<dependency>
<groupId>org.scalikejdbc</groupId>
<artifactId>scalikejdbc_2.11</artifactId>
<version>2.5.0</version>
</dependency>
<!-- scalikejdbc-config_2.11 -->
<dependency>
<groupId>org.scalikejdbc</groupId>
<artifactId>scalikejdbc-config_2.11</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-common -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.6.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.spark/spark-core -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>2.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.spark/spark-sql -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.11</artifactId>
<version>2.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.kudu/kudu-client -->
<dependency>
<groupId>org.apache.kudu</groupId>
<artifactId>kudu-client</artifactId>
<version>1.9.0</version>
</dependency>
<!--spark集成kudu-->
<dependency>
<groupId>org.apache.kudu</groupId>
<artifactId>kudu-spark2_2.11</artifactId>
<version>1.9.0</version>
</dependency>
<!--执行sql脚本-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
<!--读取配置-->
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.8</version>
</dependency>
<!--clickhouse-->
<dependency>
<groupId>cc.blynk.clickhouse</groupId>
<artifactId>clickhouse4j</artifactId>
<version>1.4.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.36</version>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--kafka-->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 这是个编译scala代码的 -->
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<id>scala-compile-first</id>
<phase>process-resources</phase>
<goals>
<goal>add-source</goal>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 这是个编译java代码的 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<!--注意这里使用jdk8,否则不能使用java8的lambda表达式和流API-->
<source>8</source>
<target>8</target>
<encoding>UTF-8</encoding>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<!--maven-assembly-plugin不能打包spring Framework框架的项目,
可以使用maven-shade-plugin插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.5</version>
<configuration>
<archive>
<manifest>
<mainClass>com.tal.mysql2kudu.MysqlToKudu_v1</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
2.将KafkaProducer利用lazy val的方式进行包装, 创建KafkaSink
package com.tal.spark
import java.util.concurrent.Future
import org.apache.kafka.clients.producer.{KafkaProducer, ProducerRecord, RecordMetadata}
class KafkaSink[K, V](createProducer: () => KafkaProducer[K, V]) extends Serializable {
/* This is the key idea that allows us to work around running into
NotSerializableExceptions. */
lazy val producer = createProducer()
def send(topic: String, key: K, value: V): Future[RecordMetadata] =
producer.send(new ProducerRecord[K, V](topic, key, value))
def send(topic: String, value: V): Future[RecordMetadata] =
producer.send(new ProducerRecord[K, V](topic, value))
def send(topic: String, partition: Int, key: K, value: V): Future[RecordMetadata] =
producer.send(new ProducerRecord[K, V](topic, partition, key, value))
}
object KafkaSink {
import scala.collection.JavaConversions._
def apply[K, V](config: Map[String, Object]): KafkaSink[K, V] = {
val createProducerFunc = () => {
val producer = new KafkaProducer[K, V](config)
sys.addShutdownHook {
// Ensure that, on executor JVM shutdown, the Kafka producer sends
// any buffered messages to Kafka before shutting down.
println("KafkaSink close producer")
producer.close()
}
producer
}
new KafkaSink(createProducerFunc)
}
def apply[K, V](config: java.util.Properties): KafkaSink[K, V] = apply(config.toMap)
}
3.利用广播变量,将KafkaProducer广播到每一个executor
完整代码
package com.tal.spark
import java.util.Properties
import com.alibaba.fastjson.JSONObject
import org.apache.kafka.clients.producer.KafkaProducer
import org.apache.kafka.common.serialization.StringSerializer
import org.apache.spark.broadcast.Broadcast
import org.apache.spark.sql.{DataFrame, SparkSession}
import org.slf4j.{Logger, LoggerFactory}
/**
* @description: TODO 读kudu写入kafka
* @author: HaoWu
* @create: 2021年06月30日
*/
object Kudu2Kafka {
private val logger: Logger = LoggerFactory.getLogger(Kudu2Kafka.getClass)
//kudu配置信息
private val kuduMaster = "hadoop101:7051"
//private val kuduTableName1 = "impala::dwddb.rt_dwd_rm_distribution_res_data_detail_new"
private val kuduTableName = "person"
//kafka 配置信息
private val bootstrapServers = "hadoop102:9092"
private val topic = "kudu_to_kafka_test"
val schema = Array("id", "CompanyId", "WorkId", "Name", "Gender", "Photo")
def main(args: Array[String]): Unit = {
// 构建SparkSession
/* val spark: SparkSession = SparkSession
.builder()
.config("spark.default.parallelism", 200)
.config("spark.shuffle.file.buffer", "128k")
.config("spark.reducer.maxSizeInFlight", "96m")
.config("spark.shuffle.memoryFraction", 0.3)
.config("spark.storage.memoryFraction", 0.3)
.enableHiveSupport()
.getOrCreate()*/
//1. 构建SparkSession实例对象
val spark: SparkSession = SparkSession.builder()
.master("local[2]")
.config("spark.sql.shuffle.partitions", "2")
.config("spark.default.parallelism", 200)
.config("spark.shuffle.file.buffer", "128k")
.config("spark.reducer.maxSizeInFlight", "96m")
.config("spark.shuffle.memoryFraction", 0.3)
.config("spark.storage.memoryFraction", 0.3)
.getOrCreate()
logger.info("加载kudu数据~~")
val time1 = System.currentTimeMillis()
val result: DataFrame = getKuduData(spark, kuduMaster, kuduTableName)
val time2 = System.currentTimeMillis()
val time = time2 - time1
logger.info("加载完成~~~:耗时:" + time + " ms!")
logger.info("数据开始发送到kafka")
write2Kafka(result, spark, 3,bootstrapServers,topic)
logger.info("-----> 数据发送到kafka完成完成!!! <-------")
spark.stop()
}
/**
* TODO 获取 kudu DF
*
* @param spark
* @param kuduMaster
* @param kuduTableName
*/
def getKuduData(spark: SparkSession, kuduMaster: String, kuduTableName: String): DataFrame = {
import spark.implicits._
// 1. 定义 map 集合,封装 kudu的master地址.表名
val options = Map(
"kudu.master" -> kuduMaster,
"kudu.table" -> kuduTableName,
// 200M
"kudu.batchSize" -> "419430400",
// 10G
"kudu.splitSizeBytes" -> "10737418240",
"kudu.keepAlivePeriodMs" -> "36000000",
"kudu.scanRequestTimeoutMs" -> "36000000",
"kudu.faultTolerantScan" -> "true",
"kudu.scanLocality" -> "leader_only" // 设置, 否则可能出现scanner not found异常
)
// 2. 从Kudu表加载数据
val kuduDF: DataFrame = spark.read
.format("kudu")
.options(options)
.load()
//打印
// kuduDF.printSchema()
// kuduDF.show(10, truncate = false)
val tempView = "person"
kuduDF.createOrReplaceTempView(tempView)
val sql =
s"""
|select
| row_number() over(order by CompanyId) as id,
| CompanyId,
| WorkId,
| Name,
| Gender,
| Photo
|from ${tempView}
|""".stripMargin
val result: DataFrame = spark.sql(sql)
result
}
/**
* TODO 写出 kafka
*
* @param result
* @param spark
* @param numPartitions
*/
def write2Kafka(result: DataFrame, spark: SparkSession, numPartitions: Int,bootstrapServers:String,topic:String): Unit = {
// 广播KafkaSink
val kafkaProducer: Broadcast[KafkaSink[String, String]] = {
val kafkaProducerConfig = {
val p = new Properties()
p.setProperty("bootstrap.servers",bootstrapServers)
p.setProperty("key.serializer", classOf[StringSerializer].getName)
p.setProperty("value.serializer", classOf[StringSerializer].getName)
p
}
logger.warn("kafka producer init done!")
spark.sparkContext.broadcast(KafkaSink[String, String](kafkaProducerConfig))
}
//输出到kafka
try {
result.foreach(
row => {
val jsonObj = new JSONObject()
schema.foreach(field => {
val fieldKey = field
val fieldValue = row.getAs[Any](fieldKey)
jsonObj.put(fieldKey, fieldValue)
})
kafkaProducer.value.send(topic,jsonObj.toString)
})
} catch {
case ex:Exception =>
logger.error("写入kafka异常,异常为:"+ex)
throw ex
}
}
}
Spark(二十一)【SparkSQL读取Kudu,写入Kafka】的更多相关文章
- storm集成kafka的应用,从kafka读取,写入kafka
storm集成kafka的应用,从kafka读取,写入kafka by 小闪电 0前言 storm的主要作用是进行流式的实时计算,对于一直产生的数据流处理是非常迅速的,然而大部分数据并不是均匀的数据流 ...
- 金融量化分析【day110】:Pandas-DataFrame读取与写入
一.DataFrame DataFrame是一个表格型的数据结构,含有一组有序的列 DataFrame可以被看作是有Series组成的字典并且工用一个索引 1.创建方式 pd.DataFrame({' ...
- Flume 读取RabbitMq消息队列消息,并将消息写入kafka
首先是关于flume的基础介绍 组件名称 功能介绍 Agent代理 使用JVM 运行Flume.每台机器运行一个agent,但是可以在一个agent中包含多个sources和sinks. Client ...
- Spark学习之数据读取与保存总结(二)
8.Hadoop输入输出格式 除了 Spark 封装的格式之外,也可以与任何 Hadoop 支持的格式交互.Spark 支持新旧两套Hadoop 文件 API,提供了很大的灵活性. 要使用新版的 Ha ...
- Kafka设计解析(二十一)关于Kafka幂等producer的讨论
转载自 huxihx,原文链接 关于Kafka幂等producer的讨论 众所周知,Kafka 0.11.0.0版本正式支持精确一次处理语义(exactly once semantics,下称EOS) ...
- 构建一个flink程序,从kafka读取然后写入MYSQL
最近flink已经变得比较流行了,所以大家要了解flink并且使用flink.现在最流行的实时计算应该就是flink了,它具有了流计算和批处理功能.它可以处理有界数据和无界数据,也就是可以处理永远生产 ...
- spark基础知识介绍(包含foreachPartition写入mysql)
数据本地性 数据计算尽可能在数据所在的节点上运行,这样可以减少数据在网络上的传输,毕竟移动计算比移动数据代价小很多.进一步看,数据如果在运行节点的内存中,就能够进一步减少磁盘的I/O的传输.在spar ...
- 牢记!SQL Server数据库开发的二十一条注意点
如果你正在负责一个基于SQL Server的项目,或者你刚刚接触SQL Server,你都有可能要面临一些数据库性能的问题,这篇文章会为你提供一些有用的指导(其中大多数也可以用于其它的DBMS). ...
- SQL Server数据库开发的二十一条军规
如果你正在负责一个基于SQL Server的项目,或者你刚刚接触SQL Server,你都有可能要面临一些数据库性能的问题,这篇文章会为你提供一些有用的指导(其中大多数也可以用于其它的DBMS).在这 ...
随机推荐
- MVC之三个单选按钮的切换选择
实现需求: 1.三个多选按钮中:只能同时选择限时抢购和分享金或者拼团特惠和分享金,其中限时抢购和拼团特惠不能同时选择.并且点击后显示,再次点击赢隐藏. 1 @*活动信息*@ 2 <div> ...
- hdu 5092 Seam Carving (简单数塔DP,题没读懂,,不过可以分析样例)
题意: 给一个m*n的矩阵,每格上有一个数. 找从第1行到第m行的一条路径,使得这条路径上的数之和最小. 路径必须满足相邻两行所选的两个数的纵坐标相邻(即一个格子必须是另一个格子的周围八个格子中的一个 ...
- 使用Visual Studio 2019将ASP.NET Core发布为linux-arm64程序
前言 前段时间入手了一台树莓派4B,一直闲置未使用,最近工作需要,要在上面跑下.NET Core程序,由于树莓派4B使用的是ARM架构,并且支持64位操作系统,为了充分发挥树莓派性能,我的这台树莓派安 ...
- google-chrome 启动报错 nss_util.cc(627)] NSS_VersionCheck("3.26") failed. NSS >= 3.26 is required
一.错误情况 报错如下: [0807/144244.712736:FATAL:nss_util.cc(627)] NSS_VersionCheck("3.26") failed. ...
- Django 中间件 详细总结
一.什么是中间件 中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出.因为改变的是全局,所以需要谨慎实用,用不好会影 ...
- mybatis替换成mybatisplus后报错mybatisplus Invalid bound statement (not found):
项目原来是mybatis,之后由于生成代码不方便,觉得替换成mybatisplus,引入mybatisplus后,启动项目报错mybatisplus Invalid bound statement ( ...
- FastApi下载文件
FastApi下载文件 记得之前我们讲过生成excel文件的事情,那么如何把服务器生成的excel文件正确发送给用户呢? 今天我们就来说说在FastApi中如何正确让用户下载到想要的文件. 基本流程 ...
- 天冷了,任务栏养只猫吧「GitHub 热点速览 v.21.46」
作者:HelloGitHub-小鱼干 运动能带来热量,盘猫也是,RunCat_for_windows 是一只奔跑在任务栏的猫,一定能给你的电脑带来一丝冬日的温暖.当然送温暖的除了任务栏小猫咪之外,还有 ...
- 网页视频不能自动播放?HTML5 video报错Uncaught (in promise) DOMException解决方法
话说发哥四年前写了一个网页,如上图效果,实际网址http://pano.z01.com ,话说做好时是正常的,突然某一天,客户说你这个网站动画不见了,这是什么原因? 结果检查脚本一切正常. 其实也不是 ...
- OpenShift S2I 概念及流程
S2I 概念 S2I(Source To Image)即从源码到镜像的一个过程,OpenShift 将它作为基础功能提供给用户,包含 S2I CLI 工具 与 S2I 流程.通过这些工具和既定流程,能 ...