Structured Streaming Source

使用 Structured Streaming 最重要的就是对 Streaming DataFrame 和 Streaming DataSet 进行各种操作.

从 Spark2.0 开始, DataFrame 和 DataSet 可以表示静态有界的表, 也可以表示流式无界表.

与静态 Datasets/DataFrames 类似,我们可以使用公共入口点 SparkSession 从流数据源创建流式 Datasets/DataFrames,并对它们应用与静态 Datasets/DataFrames 相同的操作。

通过spark.readStream()得到一个DataStreamReader对象, 然后通过这个对象加载流式数据源, 就得到一个流式的 DataFrame.

park 内置了几个流式数据源, 基本可以满足我们的所有需求.

  1. File source 读取文件夹中的文件作为流式数据. 支持的文件格式: text, csv, josn, orc, parquet. 注意, 文件必须放置的给定的目录中, 在大多数文件系统中, 可以通过移动操作来完成.
  2. kafka source 从 kafka 读取数据. 目前兼容 kafka 0.10.0+ 版本
  3. socket source 用于测试. 可以从 socket 连接中读取 UTF8 的文本数据. 侦听的 socket 位于驱动中. 注意, 这个数据源仅仅用于测试. 做不到exactly-once,因为socket停了数据就没了
  4. rate source 用于测试. 以每秒指定的行数生成数据,每个输出行包含一个 timestamp 和 value。其中 timestamp 是一个 Timestamp类型(信息产生的时间),并且 value 是 Long 包含消息的数量. 用于测试和基准测试.
SourceOptionsFault-tolerantNotes
File sourcepath: path to the input directory, and common to all file formats. maxFilesPerTrigger: maximum number of new files to be considered in every trigger (default: no max) latestFirst: whether to process the latest new files first, useful when there is a large backlog of files (default: false) fileNameOnly: whether to check new files based on only the filename instead of on the full path (default: false). With this set to true, the following files would be considered as the same file, because their filenames, “dataset.txt”, are the same: “file:///dataset.txt” “s3://a/dataset.txt” “s3n://a/b/dataset.txt” “s3a://a/b/c/dataset.txt” For file-format-specific options, see the related methods in DataStreamReader(Scala/Java/Python/R). E.g. for “parquet” format options see DataStreamReader.parquet(). In addition, there are session configurations that affect certain file-formats. See the SQL Programming Guide for more details. E.g., for “parquet”, see Parquet configuration section.YesSupports glob paths, but does not support multiple comma-separated paths/globs.Option ‘basePath’ must be a directory. Schema must be specified when creating a streaming source DataFrame. If some files already exist in the directory, then depending on the file format you may be able to create a static DataFrame on that directory with ‘spark.read.load(directory)’ and infer schema from it.
Socket Sourcehost: host to connect to, must be specified port: port to connect to, must be specifiedNo
Rate SourcerowsPerSecond (e.g. 100, default: 1): How many rows should be generated per second. rampUpTime (e.g. 5s, default: 0s): How long to ramp up before the generating speed becomes rowsPerSecond. Using finer granularities than seconds will be truncated to integer seconds. numPartitions (e.g. 10, default: Spark’s default parallelism): The partition number for the generated rows. The source will try its best to reach rowsPerSecond, but the query may be resource constrained, and numPartitions can be tweaked to help reach the desired speed.Yes
Kafka SourceSee the Kafka Integration Guide.Yes

socket source

具体案例参考前面的快速入门

file source

路径指定到文件夹 ,readStream必须指定schema;read可以推断文件类型

读取普通文件夹内的文件

  • ```scala

    import org.apache.spark.sql.streaming.{StreamingQuery, Trigger}
    import org.apache.spark.sql.types.{LongType, StringType, StructType}
    import org.apache.spark.sql.{DataFrame, SparkSession}

    object ReadFromFile {
    def main(args: Array[String]): Unit = {
    val spark: SparkSession = SparkSession
    .builder()
    .master(“local[*]”)
    .appName(“ReadFromFile”)
    .getOrCreate()

        // 定义 Schema, 用于指定列名以及列中的数据类型
        val userSchema: StructType = new StructType().add("name", StringType).add("age", LongType).add("job", StringType)
        val user: DataFrame = spark.readStream
            .format("csv")
        
            .schema(userSchema) // 指定schema
        
            .load("/Users/lzc/Desktop/csv")  // 必须是目录, 不能是文件名
    
        val query: StreamingQuery = user.writeStream
            .outputMode("append")
            .trigger(Trigger.ProcessingTime(0)) // 触发器 数字表示毫秒值. 0 表示立即处理
            .format("console")
            .start()
        query.awaitTermination()
    }
    

    }

注意: 一个文件读取完 ,更改文件内数据是监听不到

前面获取user的代码也可以使用下面的替换:

val user: DataFrame = spark.readStream
            .schema(userSchema)
            .csv("/Users/lzc/Desktop/csv")

读取自动分区的文件夹内的文件

当文件夹被命名为 “key=value” 形式时, Structured Streaming 会自动递归遍历当前文件夹下的所有子文件夹, 并根据文件名实现自动分区.

如果文件夹的命名规则不是"key=value"形式, 则不会触发自动分区. 另外, 同级目录下的文件夹的命名规则必须一致.

  • 步骤 1: 创建如下文件内容:

user1.csv

lisi,male,18
zhiling,female,28

user2.csv

lili,femal,19
fengjie,female,40
  • 步骤 2: 创建如下代码
import org.apache.spark.sql.streaming.{StreamingQuery, Trigger}
import org.apache.spark.sql.types.{IntegerType, LongType, StringType, StructType}
import org.apache.spark.sql.{DataFrame, SparkSession}

object ReadFromFile2 {
    def main(args: Array[String]): Unit = {
        val spark: SparkSession = SparkSession
            .builder()
            .master("local[*]")
            .appName("ReadFromFile")
            .getOrCreate()

        // 定义 Schema, 用于指定列名以及列中的数据类型
        val userSchema: StructType = new StructType().add("name", StringType).add("sex", StringType).add("age", IntegerType)

        val user: DataFrame = spark.readStream
            .schema(userSchema)
            .csv("/Users/lzc/Desktop/csv")

        val query: StreamingQuery = user.writeStream
            .outputMode("append")
            .trigger(Trigger.ProcessingTime(0)) // 触发器 数字表示毫秒值. 0 表示立即处理
            .format("console")
            .start()
        query.awaitTermination()
    }
}

Kafka source

参考文档: http://spark.apache.org/docs/latest/structured-streaming-kafka-integration.html

以 Streaming 模式创建 Kafka 工作流

import org.apache.spark.sql.streaming.Trigger
import org.apache.spark.sql.{DataFrame, SparkSession}

object KafkaSourceDemo {
    def main(args: Array[String]): Unit = {
        val spark: SparkSession = SparkSession
            .builder()
            .master("local[*]")
            .appName("KafkaSourceDemo")
            .getOrCreate()

        // 得到的 df 的 schema 是固定的: key,value,topic,partition,offset,timestamp,timestampType
        val df: DataFrame = spark.readStream
            .format("kafka") // 设置 kafka 数据源
            .option("kafka.bootstrap.servers", "hadoop201:9092,hadoop202:9092,hadoop203:9092")
            .option("subscribe", "topic1") // 也可以订阅多个主题:   "topic1,topic2"
            .load


        df.writeStream
            .outputMode("update")
            .format("console")
            .trigger(Trigger.Continuous(1000))
            // timestamp显示完整时间
            .option("truncate",false)
            .start
            .awaitTermination()
    }
}

对于kafka来说格式是固定的:

value:字节数组

timestamp:kafka写入数据时间戳

import org.apache.spark.sql.streaming.Trigger
import org.apache.spark.sql.{DataFrame, Dataset, SparkSession}

object KafkaSourceDemo2 {
    def main(args: Array[String]): Unit = {
        val spark: SparkSession = SparkSession
            .builder()
            .master("local[*]")
            .appName("KafkaSourceDemo")
            .getOrCreate()
        import spark.implicits._
        // 得到的 df 的 schema 是固定的: key,value,topic,partition,offset,timestamp,timestampType
        val lines: Dataset[String] = spark.readStream
            .format("kafka") // 设置 kafka 数据源
            .option("kafka.bootstrap.servers", "hadoop201:9092,hadoop202:9092,hadoop203:9092")
            .option("subscribe", "topic1") // 也可以订阅多个主题:   "topic1,topic2"
            .load
            // 转换成string
            .selectExpr("CAST(value AS string)")
            .as[String]
        val query: DataFrame = lines.flatMap(_.split("\\W+")).groupBy("value").count()
        query.writeStream
            .outputMode("complete")
            .format("console")
            .option("checkpointLocation", "./ck1")  // 下次启动的时候, 可以从上次的位置开始读取
            .start
            .awaitTermination()
    }
}

通过 Batch 模式创建 Kafka 工作流

这种模式一般需要设置消费的其实偏移量和结束偏移量, 如果不设置 checkpoint 的情况下, 默认起始偏移量 earliest, 结束偏移量为 latest.

该模式为一次性作业(批处理), 而非持续性的处理数据.

import org.apache.spark.sql.{DataFrame, Dataset, SparkSession}

object KafkaSourceDemo3 {
    def main(args: Array[String]): Unit = {
        val spark: SparkSession = SparkSession
            .builder()
            .master("local[*]")
            .appName("KafkaSourceDemo")
            .getOrCreate()
        import spark.implicits._

        val lines: Dataset[String] = spark.read  // 使用 read 方法,而不是 readStream 方法
            .format("kafka") // 设置 kafka 数据源
            .option("kafka.bootstrap.servers", "hadoop201:9092,hadoop202:9092,hadoop203:9092")
            .option("subscribe", "topic1")
            .option("startingOffsets", "earliest")
            .option("endingOffsets", "latest")
            .load
            .selectExpr("CAST(value AS STRING)")
            .as[String]

        val query: DataFrame = lines.flatMap(_.split("\\W+")).groupBy("value").count()

        query.write   // 使用 write 而不是 writeStream
            .format("console")
            .save()
    }
}

Rate Source

以固定的速率生成固定格式的数据, 用来测试 Structured Streaming 的性能.

import org.apache.spark.sql.streaming.Trigger
import org.apache.spark.sql.{DataFrame, SparkSession}

object RateSourceDemo {
    def main(args: Array[String]): Unit = {
        val spark: SparkSession = SparkSession
            .builder()
            .master("local[*]")
            .appName("RateSourceDemo")
            .getOrCreate()

        val rows: DataFrame = spark.readStream
            .format("rate") // 设置数据源为 rate
            .option("rowsPerSecond", 10) // 设置每秒产生的数据的条数, 默认是 1
            .option("rampUpTime", 1) // 设置多少秒到达指定速率 默认为 0
            .option("numPartitions", 2) /// 设置分区数  默认是 spark 的默认并行度
            .load

        rows.writeStream
            .outputMode("append")
            .trigger(Trigger.Continuous(1000))
            .format("console")
            .start()
            .awaitTermination()
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Structured Streaming 是 Apache Spark 的一种流式处理引擎,它可以帮助我们对流式数据进行转换、处理和聚合。Structured Streaming 使用了基于 SQL 的语法,因此我们可以使用熟悉的 SQL 语句来对流式数据进行操作。例如,我们可以使用以下 SQL 语句对流式数据进行过滤: ``` SELECT * FROM stream WHERE value > 5 ``` 或者使用以下 SQL 语句对流式数据进行分组并计算每组的平均值: ``` SELECT key, AVG(value) FROM stream GROUP BY key ``` Structured Streaming支持联机处理,即可以对流式数据进行实时处理,并将结果实时输出。这使得我们可以使用 Structured Streaming 实现各种实时数据处理任务,如实时统计、实时分析等。 ### 回答2: 结构化流式处理(Structured Streaming)是一种用于处理实时数据的数据处理引擎。它允许开发人员使用SQL查询实时流数据,无需编写复杂的流式处理程序。Structured Streaming SQL是一种使用SQL语句对实时数据进行查询和操作的方式。 Structured Streaming SQL可以通过Spark SQL的语法和功能来处理实时数据。它可以将实时数据以表的形式表示,并且支持标准SQL查询操作,例如选择、过滤、聚合和连接操作。在Structured Streaming SQL中,开发人员可以使用常见的SQL函数和操作符来处理实时数据。 Structured Streaming SQL还支持时间窗口操作,可以通过指定窗口长度和滑动步长来对实时数据进行分组和聚合。此外,Structured Streaming SQL还支持流-静态表连接,可以将实时流数据与静态数据表进行关联操作,以便获得更丰富的分析结果。 Structured Streaming SQL的一个主要特点是其容错性和弹性。当发生故障或数据丢失时,Structured Streaming可以自动从上次检查点恢复,并且能够动态调整计算资源以适应数据的变化。 总而言之,Structured Streaming SQL提供了一种简单、灵活且易于使用的方式来处理和分析实时数据。通过使用SQL语句,开发人员可以更快地构建和迭代实时数据处理应用程序,从而更好地理解和利用实时数据的价值。 ### 回答3: Structured Streaming是Spark提供的一种流处理方式,可以使用SQL语句来对流式数据进行处理和分析。它使用了DataFrame和Dataset这两种抽象概念,提供了与传统批处理相似的编程模型,可以方便地进行流处理任务。 与传统的流处理方式相比,Structured Streaming具有以下特点: 1. 连接机制:Structured Streaming可以连接各种输入源和输出目标,如Kafka、消息队列等,方便处理不同来源和去向的数据。 2. 强大的API支持Structured Streaming提供了丰富的API,可以通过SQL语句或DataFrame/Dataset API来执行流处理任务,使得开发人员可以使用熟悉的SQL语言进行流处理操作。 3. 实时处理:Structured Streaming支持实时处理,可以以毫秒级的延迟来处理数据,使得我们能够实时处理数据流并及时生成结果。 4. 容错性:Structured Streaming具有高度的容错性,能够自动处理失败和恢复。它使用了Spark的弹性分布式数据集(RDD)来进行数据处理,一旦发生故障,它可以自动从上一次处理的结果继续进行处理。 5. 一致性:Structured Streaming保证了事件的顺序和一致性,保证数据的完整性和正确性。 6. 扩展性:Structured Streaming具有良好的扩展性,可以根据实际需求进行水平扩展,以满足大规模数据处理的需求。 结构化流处理SQL的使用可以极大地简化流处理任务的编写和维护,使得开发人员能够更加专注于业务逻辑的实现。通过使用结构化流处理SQL,我们可以方便地进行各种流处理操作,包括过滤、转换、聚合以及窗口操作等,同时可以借助Spark的优化能力来提高处理性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值