Structured Streaming

本文深入探讨了Spark Streaming的演进,重点关注Structured Streaming。介绍了Spark编程模型的演变,包括RDD、DataFrame、Dataset的优缺点和序列化过程。详细阐述了Structured Streaming的概念、体系结构、Source和Sink,并通过实例展示了如何从HDFS和Kafka中读取数据。文章还讨论了数据流处理的触发器、错误恢复和容错语义,以及如何实现exactly-once语义。
摘要由CSDN通过智能技术生成

Structured Streaming

Structured Streaming 是 Spark Streaming 的进化版, 如果了解了 Spark 的各⽅⾯的进化过程, 有助于理

解 Structured Streaming 的使命和作⽤

\1. Spark 的 API 进化过程

\2. Spark 的序列化进化过程

\3. Spark Streaming 和 Structured Streaming

Spark 编程模型的进化过程

⽬标

Spark 的进化过程中, ⼀个⾮常重要的组成部分就是编程模型的进化, 通过编程模型可以看得出来内在的问题和

解决⽅案

过程

\1. 编程模型 RDD 的优点和缺陷

\2. 编程模型 DataFrame 的优点和缺陷

\3. 编程模型 Dataset 的优点和缺陷

分析 编程模型
RDD rdd.flatMap(.split(" "))<br /> .map((, 1)) <br /> .reduceByKey(_ + _) <br /> .collect <br /> 针对⾃定义数据对象进⾏处理, 可以处理任意类型的对象, ⽐较符合⾯向对象 <br /> RDD ⽆法感知到数据的结构, ⽆法针对数据结构进⾏编程
DataFrame spark.read<br />.csv("...").<br />where( "age"=!="")<br />groupBy("age")<br />.show()<br />1. DataFrame 保留有数据的元信息, API 针对数据的结构进⾏处理, 例如说可以根据数据的某⼀列进⾏排序或者分组<br />2. DataFrame 在执⾏的时候会经过 Catalyst 进⾏优化, 并且序列化更加⾼效, 性能会更好<br />3. DataFrame 只能处理结构化的数据, ⽆法处理⾮结构化的数据, 因为 DataFrame 的内部使⽤ Row 对象保存数据<br />4. Spark 为 DataFrame 设计了新的数据读写框架, 更加强⼤, ⽀持的数据源众多
DataSet spark.read<br />.csv("...")<br />.as[Person]<br />.where(.age!= "")<br />.groupByKey(.age)<br />.count()<br />.show()<br />1. Dataset 结合了 RDD 和 DataFrame 的特点,从 API 上即可以处理结构化数据, 也可以处理⾮结构化数据<br />2. Dataset 和 DataFrame 其实是⼀个东⻄, 所以 DataFrame 的性能优势, 在 Dataset 上也有

总结

RDD 的优点

\1. ⾯向对象的操作⽅式

\2. 可以处理任何类型的数据

RDD 的缺点

\1. 运⾏速度⽐较慢, 执⾏过程没有优化

\2. API ⽐较僵硬, 对结构化数据的访问和操作没有优化

DataFrame 的优点

\1. 针对结构化数据⾼度优化, 可以通过列名访问和转换数据

\2. 增加 Catalyst 优化器, 执⾏过程是优化的, 避免了因为开发者的原因影响效率

DataFrame 的缺点

\1. 只能操作结构化数据

\2. 只有⽆类型的 API , 也就是只能针对列和 SQL 操作数据, API 依然僵硬

Dataset 的优点

\1. 结合了 RDD 和 DataFrame 的 API , 既可以操作结构化数据, 也可以操作⾮结构化数据

\1. 既有有类型的 API 也有⽆类型的 API , 灵活选择

Spark 的 序列化 的进化过程

⽬标和问题

⽬标

Spark 中的序列化过程决定了数据如何存储, 是性能优化⼀个⾮常重要的着眼点, Spark 的进化并不只是针对

编程模型提供的 API , 在⼤数据处理中, 也必须要考虑性能

问题

\1. 序列化和反序列化是什么 ?

\2. Spark 中什么地⽅⽤到序列化和反序列化 ?

\3. RDD 的序列化和反序列化如何实现 ?

\4. Dataset 的序列化和反序列化如何实现 ?

什么是序列化和序列化?

序列化是什么

\1. 序列化的作⽤就是可以将对象的内容变成⼆进制, 存⼊⽂件中保存

\2. 反序列化指的是将保存下来的⼆进制对象数据恢复成对象

序列化对对象的要求

\1. 对象必须实现 Serializable 接⼝

\2. 对象中的所有属性必须都要可以被序列化, 如果出现⽆法被序列化的属性, 则序列化失败

限制

\1. 对象被序列化后, ⽣成的⼆进制⽂件中, 包含了很多环境信息, 如对象头, 对象中的属性字段等, 所以内容相

对较⼤

\2. 因为数据量⼤, 所以序列化和反序列化的过程⽐较慢

序列化的应⽤场景

\1. 持久化对象数据

\1. ⽹络中不能传输 Java 对象, 只能将其序列化后传输⼆进制数据

在 Spark 中的序列化和反序列化的应⽤场景

Task 分发

Task 是⼀个对象, 想在⽹络中传输对象就必须要先序列化

RDD 缓存

val rdd1 = rdd.flatMap(_.split(" "))
 .map((_, 1))
 .reduceByKey(_ + _)
rdd1.cache
rdd1.collect

RDD 中处理的是对象, 例如说字符串, Person 对象等

如果缓存 RDD 中的数据, 就需要缓存这些对象

对象是不能存在⽂件中的, 必须要将对象序列化后, 将⼆进制数据存⼊⽂件

⼴播变量

⼴播变量会分发到不同的机器上, 这个过程中需要使⽤⽹络, 对象在⽹络中传输就必须先被序列化

Shuffle 过程

Shuffle 过程是由 Reducer 从 Mapper 中拉取数据, 这⾥⾯涉及到两个需要序列化对象的原因

RDD 中的数据对象需要在 Mapper 端落盘缓存, 等待拉取

Mapper 和 Reducer 要传输数据对象

Spark Streaming 的 Receiver

Spark Streaming 中获取数据的组件叫做 Receiver , 获取到的数据也是对象形式, 在获取到以后需要落盘

暂存, 就需要对数据对象进⾏序列化

算⼦引⽤外部对象

class userserializable(i: Int)
rdd.map(i => new Unserializable(i))
 .collect
 .foreach(println)

在 Map 算⼦的函数中, 传⼊了⼀个 Unserializable 的对象

Map 算⼦的函数是会在整个集群中运⾏的, 那 Unserializable 对象就需要跟随 Map 算⼦的函数被传

输到不同的节点上

如果 Unserializable 不能被序列化, 则会报错

RDD 的序列化

RDD 的序列化

RDD 的序列化只能使⽤ Java 序列化器, 或者 Kryo 序列化器

为什么?

RDD 中存放的是数据对象, 要保留所有的数据就必须要对对象的元信息进⾏保存, 例如对象头之类的 保存⼀
整个对象, 内存占⽤和效率会⽐较低⼀些

Kryo 是什么

Kryo 是 Spark 引⼊的⼀个外部的序列化⼯具, 可以增快 RDD 的运⾏速度 因为 Kryo 序列化后的对象

更⼩, 序列化和反序列化的速度⾮常快 在 RDD 中使⽤ Kryo 的过程如下

val conf = new SparkConf()
 .setMaster("local[2]")
 .setAppName("KyroTest")
conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
conf.registerKryoClasses(Array(classOf[Person]))
val sc = new SparkContext(conf)
rdd.map(arr => Person(arr(0), arr(1), arr(2)))

DataFrame 和 Dataset 中的序列化

历史的问题

RDD 中⽆法感知数据的组成, ⽆法感知数据结构, 只能以对象的形式处理数据

DataFrame 和 Dataset 的特点

DataFrame 和 Dataset 是为结构化数据优化的

在 DataFrame 和 Dataset 中, 数据和数据的 Schema 是分开存储的

spark.read
 .csv("...")
 .where($"name" =!= "")
 .groupBy($"name")
 .map(row: Row => row)
 .show()

DataFrame 中没有数据对象这个概念, 所有的数据都以⾏的形式存在于 Row 对象中, Row 中记录了每

⾏数据的结构, 包括列名, 类型等

Dataset 中上层可以提供有类型的 API , ⽤以操作数据, 但是在内部, ⽆论是什么类型的数据对象 Dataset 都使

⽤⼀个叫做 InternalRow 的类型的对象存储数据

val dataset: Dataset[Person] = spark.read.csv(...).as[Person]

总结

\1. 当需要将对象缓存下来的时候, 或者在⽹络中传输的时候, 要把

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值