185-spark-核心编程-Streaming:
数据处理延迟的长短分为:实时数据处理(毫秒级别),离线数据处理(小时,天)
数据处理的方式分为:流式数据处理(streaming,来一点处理一点),批量数据处理(batch,来一批数据处理一批)
sparkstreaming,准实时(秒,分钟),微批次(时间)的数据处理框架。 用于流式数据的处理
SparkStreaming 架构图
Spark Streaming 使用离散化流(discretized stream)作为抽象表示,叫作 DStream。DStream 是随时间推移而收到的数据的序列。在内部,每个时间区间收到的数据都作为 RDD 存在,而 DStream 是由这些 RDD 所组成的序列(因此得名“离散化”)。所以简单来将,DStream 就是对 RDD 在实时数据处理场景的一种封装。
背压机制
Spark 1.5 以前版本,如果要限制 Receiver 的数据接收速率,可以通过设置静态配制参数“spark.streaming.receiver.maxRate”的值来实现,虽然可以通过限制接收速率,来适配当前的处理能力,防止内存溢出,但也会引入其它问题。比如:producer 数据生产高于 maxRate,当前集群处理能力也高于 maxRate,这就会造成资源利用率下降等问题。
为更好协调数据接收速率与资源处理能力,1.5 版本开始 Spark Streaming 可以动态控制数据接收速率来适配集群数据处理能力。背压机制(即 Spark Streaming Backpressure): 根据JobScheduler 反馈作业的执行信息来动态调整 Receiver 数据接收率。通过属性“spark.streaming.backpressure.enabled”来控制是否启用 backpressure 机制,默认值false,即不启用。
SparkStream入门操作
WordCount 案例实操
➢ 需求:使用 netcat 工具向 9999 端口不断的发送数据,通过 SparkStreaming 读取端口数据并统计不同单词出现的次数
window-netcat的使用 https://eternallybored.org/misc/netcat/
建议直接使用linux nc -lk 9999
代码:SparkStreaming01_WordCount,SparkStreaming02_Queue
自定义数据采集器 SparkStreaming03_DIY
package spark.stream.com.zh
import org.apache.spark.SparkConf
import org.apache.spark.rdd.RDD
import org.apache.spark.storage.StorageLevel
import org.apache.spark.streaming.dstream.ReceiverInputDStream
import org.apache.spark.streaming.receiver.Receiver
import org.apache.spark.streaming.{Seconds, StreamingContext}
import scala.collection.mutable
import scala.util.Random
/**
* sparkstreaming wordcount的初体验
*/
object SparkStreaming03_DIY {
def main(args: Array[String]): Unit = {
//创建环境对象
val sparkConf = new SparkConf().setMaster("local[*]").setAppName("SparkStreaming")
//StreamingContext 参数1:环境配置 参数2:批量处理的周期时间(采集周期)
val ssc = new StreamingContext(sparkConf, Seconds(5))
val messageDs: ReceiverInputDStream[String] = ssc.receiverStream(new MyReceiver())
messageDs.print()
//启动采集器
ssc.start()
//等待采集器的关闭
ssc.awaitTermination()
}
/**
* 自定义数据采集器
* 1、继承Receiver,定义泛型
* 2.重写方法
*/
class MyReceiver extends Receiver[String](StorageLevel.MEMORY_ONLY) {
private var flag = true;
//表示启动时候
override def onStart(): Unit = {
new Thread(new Runnable {
override def run(): Unit = {
while (flag) {
val message = "采集的数据为: " + new Random().nextInt(10).toString
//存储
store(message)
Thread.sleep(500)
}
}
}).start()
}
//关闭
override def onStop(): Unit = {
flag = false
}
}
}
Kafka数据源(重点)
Kafka 0-10 Direct模式,通过 SparkStreaming 从 Kafka 读取数据,并将读取过来的数据做简单计算,打印到控制台。
依赖:
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming-kafka-0-10_2.12</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.10.1</version>
</dependency>
代码:spark.stream.com.zh.SparkStreaming04_Kafka,启动接收消息
启动zk和kafka
>kafkbin/kafka-topics.sh --zookeeper hadoop102:2181 --list
>bin/kafka-topics.sh --zookeeper hadoop102:2181 --create --topic kafkasparkstreamtest --partitions 3 --replication-factor 2
>kafkbin/kafka-topics.sh --zookeeper hadoop102:2181 --list
>bin/kafka-console-producer.sh --broker-list hadoop102:9092 --topic kafkasparkstreamtest
发送消息
DStream 转换
DStream 上的操作与 RDD 的类似,分为 Transformations(转换)和 Output Operations(输出)两种
无状态转化操作
Transform SparkStreaming05_State_Transform
Transform 允许 DStream 上执行任意的 RDD-to-RDD 函数。即使这些函数并没有在 DStream的 API 中暴露出来,通过该函数可以方便的扩展 Spark API。该函数每一批次调度一次。其实也就是对 DStream 中的 RDD 应用转换。
**join **SparkStreaming06_State_Join
两个流之间的 join 需要两个流的批次大小一致,这样才能做到同时触发计算。计算过程就是对当前批次的两个流中各自的 RDD 进行 join,与两个 RDD 的 join 效果相同。
有状态转化操作
UpdateStateByKey SparkStreaming05_State
//采集5秒周期数据 采集5秒周期数据 采集5秒周期数据
//[a,b,a] Data1 [a,b,b] Data2 [a,b,a] Data3
//读取data1时,记录[(a,2)(b,1)],读取data2时,[(a,3)(b,3)],读取data3时,[(a,5)(b,4)]
UpdateStateByKey 原语用于记录历史记录
-
定义状态,状态可以是一个任意的数据类型。
-
定义状态更新函数,用此函数阐明如何使用之前的状态和来自输入流的新值对状态进行更新。使用 updateStateByKey 需要对检查点目录进行配置,会使用检查点来保存状态。
WindowOperations窗体操作 SparkStreaming06_State_Window
Window Operations 可以设置窗口的大小和滑动窗口的间隔来动态的获取当前 Steaming 的允许状态。所有基于窗口的操作都需要两个参数,分别为窗口时长以及滑动步长。 注意:这两者都必须为采集周期大小的整数倍。
➢ 窗口时长:计算内容的时间范围
➢ 滑动步长:隔多久触发一次计算。
//采集5秒周期数据 采集5秒周期数据 采集5秒周期数据
//[a,b,c] Data1 [b,c,d] Data2 [a1,b1,c1] Data3
/** 窗体是10,步长为10,为单个采集周期的2倍。则,
* 一个窗体的数据为data1+data2->data3+data4(含指定步长时,不含则为data2+data3)
* */
关于 Window 的操作还有如下方法(有待进一步了解深入。入门操作和效果概念以及使用了解):
(1)window(windowLength, slideInterval): 基于对源 DStream 窗化的批次进行计算返回一个新的 Dstream;
(2)countByWindow(windowLength, slideInterval): 返回一个滑动窗口计数流中的元素个数;
(3)reduceByWindow(func, windowLength, slideInterval): 通过使用自定义函数整合滑动区间流元素来创建一个新的单元素流;
(4)reduceByKeyAndWindow(func, windowLength, slideInterval, [numTasks]): 当在一个(K,V)对的 DStream 上调用此函数,会返回一个新(K,V)对的 DStream,此处通过对滑动窗口中批次数据使用 reduce 函数来整合每个 key 的 value 值。
(5)reduceByKeyAndWindow(func, invFunc, windowLength, slideInterval, [numTasks]): 这个函数是上述函数的变化版本,每个窗口的 reduce 值都是通过用前一个窗的 reduce 值来递增计算。通过 reduce 进入到滑动窗口数据并”反向 reduce”离开窗口的旧数据来实现这个操作。一个例子是随着窗口滑动对 keys 的“加”“减”计数。通过前边介绍可以想到,这个函数只适用于可逆的 reduce 函数”,也就是这些 reduce 函数有相应的”反 reduce”函数(以参数 invFunc 形式传入)。如前述函数,reduce 任务的数量通过可选参数来配置。
DStream输出
输出操作指定了对流数据经转化操作得到的数据所要执行的操作(例如把结果推入外部数据库或输出到屏幕上)。与 RDD 中的惰性求值类似,如果一个 DStream 及其派生出的 DStream 都没有被执行输出操作,那么这些 DStream 就都不会被求值。如果 StreamingContext 中没有设定输出操作,整个 context 就都不会启动。
输出操作如下:
➢ print():在运行流程序的驱动结点上打印 DStream 中每一批次数据的最开始 10 个元素。这用于开发和调试。
➢ saveAsTextFiles(prefix, [suffix]):以 text 文件形式存储这个 DStream 的内容。每一批次的存储文件名基于参数中的 prefix 和 suffix。”prefix-Time_IN_MS[.suffix]”。
➢ saveAsObjectFiles(prefix, [suffix]):以 Java 对象序列化的方式将 Stream 中的数据保存为SequenceFiles . 每一批次的存储文件名基于参数中的为"prefix-TIME_IN_MS[.suffix]".
➢ saveAsHadoopFiles(prefix, [suffix]):将 Stream 中的数据保存为 Hadoop files. 每一批次的存储文件名基于参数中的为"prefix-TIME_IN_MS[.suffix]"。
➢ foreachRDD(func):这是最通用的输出操作,即将函数 func 用于产生于 stream 的每一个RDD。其中参数传入的函数 func 应该实现将每一个 RDD 中数据推送到外部系统,如将RDD 存入文件或者通过网络将其写入数据库。通用的输出操作 foreachRDD(),它用来对 DStream 中的 RDD 运行任意计算。这和 transform() 有些类似,都可以让我们访问任意 RDD。在 foreachRDD()中,可以重用我们在 Spark 中实现的所有行动操作。比如,常见的用例之一是把数据写到诸如 MySQL 的外部数据库中。
注意(暂时了解,后续补充):
-
连接不能写在 driver 层面(序列化)
-
如果写在 foreach 则每个 RDD 中的每一条数据都创建,得不偿失;
-
增加 foreachPartition,在分区创建(获取)
优雅关闭 SparkStreaming08_Close
流式任务需要 7*24 小时执行,但是有时涉及到升级代码需要主动停止程序,但是分布式程序,没办法做到一个个进程去杀死,所有配置优雅的关闭就显得至关重要了。使用外部文件系统来控制内部程序关闭。
数据恢复:SparkStreaming08_Resume
学习路径:https://space.bilibili.com/302417610/,如有侵权,请联系q进行删除:3623472230