Structured Streaming 初次练手

**

Structured Streaming

**

本章目标

Structured Streaming 是 Spark Streaming 的进化版, 如果了解了 Spark 的各方面的进化过程, 有助于理解 Structured Streaming 的使命和作用
本章过程
Spark 的 API 进化过程
Spark Streaming 和 Structured Streaming
1.1. Spark 编程模型的进化过程

编程模型	解释
RDD

rdd.flatMap(_.split(" "))
   .map((_, 1))
   .reduceByKey(_ + _)
   .collect
针对自定义数据对象进行处理, 可以处理任意类型的对象, 比较符合面向对象

RDD 无法感知到数据的结构, 无法针对数据结构进行编程

DataFrame

spark.read
     .csv("...")
     .where($"name" =!= "")
     .groupBy($"name")
     .show()
DataFrame 保留有数据的元信息, API 针对数据的结构进行处理, 例如说可以根据数据的某一列进行排序或者分组

DataFrame 在执行的时候会经过 Catalyst 进行优化, 并且序列化更加高效, 性能会更好

DataFrame 只能处理结构化的数据, 无法处理非结构化的数据, 因为 DataFrame 的内部使用 Row 对象保存数据

Spark 为 DataFrame 设计了新的数据读写框架, 更加强大, 支持的数据源众多

Dataset

spark.read
     .csv("...")
     .as[Person]
     .where(_.name != "")
     .groupByKey(_.name)
     .count()
     .show()
Dataset 结合了 RDD 和 DataFrame 的特点, 从 API 上即可以处理结构化数据, 也可以处理非结构化数据

Dataset 和 DataFrame 其实是一个东西, 所以 DataFrame 的性能优势, 在 Dataset 上也有


总结
RDD 的优点
面向对象的操作方式

可以处理任何类型的数据

RDD 的缺点
运行速度比较慢, 执行过程没有优化

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

DataFrame 的优点
针对结构化数据高度优化, 可以通过列名访问和转换数据

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

DataFrame 的缺点
只能操作结构化数据

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

Dataset 的优点
结合了 RDD 和 DataFrame 的 API, 既可以操作结构化数据, 也可以操作非结构化数据

既有有类型的 API 也有无类型的 API, 灵活选择
Spark Streaming 时代
Spark Streaming 其实就是 RDD 的 API 的流式工具, 其本质还是 RDD, 存储和执行过程依然类似 RDD
Structured Streaming 时代
Structured Streaming 其实就是 Dataset 的 API 的流式工具, API 和 Dataset 保持高度一致
Spark Streaming 和 Structured Streaming
Structured Streaming 相比于 Spark Streaming 的进步就类似于 Dataset 相比于 RDD 的进步

另外还有一点, Structured Streaming 已经支持了连续流模型, 也就是类似于 Flink 那样的实时流, 而不是小批量, 但在使用的时候仍然有限制, 大部分情况还是应该采用小批量模式

在 2.2.0 以后 Structured Streaming 被标注为稳定版本, 意味着以后的 Spark 流式开发不应该在采用 Spark Streaming 了

正式开始 操作

步骤
编写一个流式计算的应用, 不断的接收外部系统的消息

对消息中的单词进行词频统计

统计全局的结果

object SocketProcessor {

  def main(args: Array[String]): Unit = {

    // 1. 创建 SparkSession
    val spark = SparkSession.builder()
      .master("local[6]")
      .appName("socket_processor")
      .getOrCreate()

    spark.sparkContext.setLogLevel("ERROR")   

    import spark.implicits._

    // 2. 读取外部数据源, 并转为 Dataset[String]
    val source = spark.readStream
      .format("socket")
      .option("host", "127.0.0.1")
      .option("port", 9999)
      .load()
      .as[String]                             

    // 3. 统计词频
    val words = source.flatMap(_.split(" "))
      .map((_, 1))
      .groupByKey(_._1)
      .count()

    // 4. 输出结果
    words.writeStream
      .outputMode(OutputMode.Complete())      
      .format("console")                      
      .start()                                
      .awaitTermination()                     
  }
}

ok 整体看起来少了很多rdd操作,都是基于dataset

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值