Structured Streaming join 操作

本文详细介绍了Apache Spark的Structured Streaming如何进行流-静态数据和流-流数据的Join操作,包括内连接和外连接,并通过示例展示了如何在不同场景下使用watermark机制来处理状态无限增长的问题。此外,还提到了Structured Streaming中不支持的一些操作,如多个聚合、limit等。

join 操作

Structured Streaming 支持 streaming DataSet/DataFrame 与静态的DataSet/DataFrame 进行 join, 也支持 streaming DataSet/DataFrame与另外一个streaming DataSet/DataFrame 进行 join.

join 的结果也是持续不断的生成, 类似于前面学习的 streaming 的聚合结果.

Stream-static Joins

模拟的静态数据:

lisi,male
zhiling,female
zs,male

模拟的流式数据:

lisi,20
zhiling,40
ww,30
内连接
import org.apache.spark.sql.streaming.Trigger
import org.apache.spark.sql.{
   
   DataFrame, SparkSession}

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

        // 1. 静态 df
        val arr = Array(("lisi", "male"), ("zhiling", "female"), ("zs", "male"));
        var staticDF: DataFrame = spark.sparkContext.parallelize(arr).toDF("name", "sex")

        // 2. 流式 df
        val lines: DataFrame = spark.readStream
            .format("socket")
            .option("host", "localhost")
            .option("port", 10000)
            .load()
        val streamDF: DataFrame = lines.as[String].map(line => {
   
   
            val arr = line.split(",")
            (arr(0), arr(1).toInt)
        }).toDF("name", "age")

        // 3. join   等值内连接  a.name=b.name
        val joinResult: DataFrame = streamDF.join(staticDF, "name")  // 或者传seq("name")

        // 4. 输出
        joinResult.writeStream
            .outputMode("append")
            .format("console")
            .start
            .awaitTermination()

    }
}
+-------+---+------+
|   name|age|   sex|
+-------+---+------+
|zhiling| 40|female|
|   lisi| 20|  male|
+-------+---+------+
外连接
val joinResult: DataFrame = streamDF.join(staticDF, Seq("name"), "left") // 流在那边写那边
+-------+---+------+
|   name|age|   sex
### 关于 Structured Streaming 的练习题 #### 题目 1: 数据处理基础 创建一个 Spark 应用程序来读取来自 Kafka 主题的数据并将其写入控制台。假设 Kafka 中的消息是以 JSON 格式的字符串形式存在的。 ```python from pyspark.sql import SparkSession from pyspark.sql.functions import col, from_json from pyspark.sql.types import StringType, StructType, StructField # 创建 Spark Session spark = SparkSession.builder \ .appName("KafkaToConsole") \ .getOrCreate() # 定义 Schema schema = StructType([ StructField("id", StringType(), True), StructField("value", StringType(), True)]) # 从 Kafka 读取消息 df = spark.readStream.format("kafka") \ .option("kafka.bootstrap.servers", "host1:port1,host2:port2") \ .option("subscribe", "topic_name") \ .load() \ .selectExpr("CAST(value AS STRING)") \ .withColumn("json", from_json(col("value"), schema)) \ .select("json.*") # 将消息打印到控制台 query = df.writeStream.outputMode("append").format("console").start() query.awaitTermination() ``` 此代码展示了如何设置 Structured Streaming 来消费 Kafka 中的数据,并通过 `readStream` 方法指定输入源,以及使用 `writeStream` 输出至控制台[^2]。 #### 题目 2: 文件读取与转换 编写一段 PySpark 程序用于读取 CSV 文件作为 DataFrame 并执行简单的聚合操作之后再保存回磁盘上的新位置。 ```python import os from pyspark.sql import SparkSession # 初始化 Spark session spark = SparkSession.builder.appName('CSVProcessing').getOrCreate() input_path = 'path/to/input.csv' output_path = 'path/to/output' if not os.path.exists(output_path): os.makedirs(output_path) # 加载 csv 文件成 dataframe df = spark.read.option("header",True).csv(input_path) # 执行一些基本变换比如按某一列分组求平均数 result_df = df.groupBy("some_column").avg().alias("average_value") # 存储结果为 parquet 文件格式 result_df.write.mode('overwrite').parquet(os.path.join(output_path,'results')) ``` 这段脚本说明了怎样利用 Structured API 对静态文件进行批处理作业;尽管这里展示的是针对批量数据的操作,但是同样的逻辑也可以应用于持续到达的新批次上以支持近实时分析需求[^4]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值