Apache Spark 第 8 章:Structured Streaming 流处理

好,第八章深入拆解 Structured Streaming,从设计哲学开始,逐层剖析。

  • 先看第一张:流处理核心模型。核心模型清楚了。
  • 接下来看微批次的执行引擎内部------每次触发时 Spark 到底做了什么:微批次执行机制和容错原理搞清楚了。
  • 接下来是最难理解的部分------Watermark 事件时间处理:Watermark 和时间窗口搞透了。
  • 接下来看 State Store 的工作机制和 Streaming 完整的读写体系:四张图把第八章完整覆盖。

下面是核心知识梳理:


核心模型(第一张) 是 Structured Streaming 最革命性的设计思想:把流抽象成一张不断追加行的无界表 。这意味着你写的代码和批处理完全一样------df.filter(...).groupBy(...).agg(...) 这套 API,批处理里能用,流处理里也能用,引擎自动把它转成增量计算。三种 Output Mode 控制每次触发后输出什么:Append 只追加新行(适合无状态或带 Watermark 的聚合),Complete 每次输出全量(全局聚合时用),Update 只输出变更行(最节省网络)。四种触发器则控制多久处理一次:ProcessingTime 固定间隔最常用,AvailableNow 用于一次性批量处理历史数据,Continuous 和 Real-Time Mode 则是追求毫秒级延迟的选项。


微批次执行周期(第二张) 是 Exactly-Once 的实现基础。每次触发分四步:查询 Source 最新 Offset → 写 WAL 日志(预先记录本批 Offset 范围)→ 执行批处理(读新数据、转换、更新 State Store)→ 写 commit 文件(确认本批完成)。Checkpoint 目录是整个容错机制的核心,offsets/ 记录每批的 Offset 范围,commits/ 记录哪些批次已完成,state/ 存储有状态算子的中间数据。恢复时的逻辑很直接:有 offset 没有 commit 说明上次失败了,重跑这批;两者都有说明已完成,跳过。


Watermark 与事件时间(第三张) 解决的是现实流处理的核心难题:网络延迟导致数据乱序到达。withWatermark("timestamp", "10 minutes") 告诉 Spark 允许最多 10 分钟的乱序延迟------Watermark 等于当前最大事件时间减去容忍值。事件时间落在 Watermark 之后的数据正常处理,落在 Watermark 之前的数据被直接丢弃。三种窗口类型的选择很清晰:滚动窗口用于每N分钟统计一次,滑动窗口用于"最近N分钟"类的实时指标,会话窗口用于用户行为分析(按活动间隙切割 Session)。


State Store 和读写体系(第四张) 是生产部署的关键。State Store 是有状态计算的存储引擎,默认的 HDFSBackedStateStore 状态存内存,适合中小状态;生产环境强烈推荐换成 RocksDBStateStore(Spark 3.2+),状态存本地磁盘,完全绕过 JVM GC,支持 TB 级超大状态,增量 Checkpoint 速度也更快。Source 端 Kafka 是生产首选,支持 Offset 回放保证 Exactly-Once;Sink 端推荐 Delta Lake,事务写入天然支持 Exactly-Once,其次是 File Sink。自定义 Sink 用 foreachBatch(推荐,批量写效率高)或 foreach(逐行,灵活但慢)。


最后附一段完整的生产级代码示例:

python 复制代码
from pyspark.sql import SparkSession
from pyspark.sql.functions import window, count, col, from_json
from pyspark.sql.types import StructType, StringType, TimestampType

spark = SparkSession.builder \
    .config("spark.sql.streaming.stateStore.providerClass",
            "org.apache.spark.sql.execution.streaming.state.RocksDBStateStoreProvider") \
    .getOrCreate()

schema = StructType() \
    .add("user_id", StringType()) \
    .add("city", StringType()) \
    .add("event_time", TimestampType())

# 读取 Kafka
df = spark.readStream \
    .format("kafka") \
    .option("kafka.bootstrap.servers", "broker:9092") \
    .option("subscribe", "orders") \
    .option("startingOffsets", "latest") \
    .load() \
    .select(from_json(col("value").cast("string"), schema).alias("d")) \
    .select("d.*")

# 带 Watermark 的滑动窗口聚合
result = df \
    .withWatermark("event_time", "10 minutes") \
    .groupBy(window("event_time", "10 minutes", "5 minutes"), "city") \
    .agg(count("*").alias("order_count"))

# 写入 Delta Lake(Exactly-Once)
query = result.writeStream \
    .format("delta") \
    .option("checkpointLocation", "s3://bucket/checkpoints/orders/") \
    .outputMode("append") \
    .trigger(processingTime="1 minute") \
    .start("s3://bucket/delta/order_stats/")

query.awaitTermination()
相关推荐
Data-Miner7 小时前
需要做财务数据分析,有什么好用的工具?从准备到出报告的实操指南
大数据·数据库·数据分析
阿里云大数据AI技术9 小时前
StarRocks × Paimon C++:加速湖上数据分析
大数据·人工智能
用户3610588626129 小时前
Flink 配置深度剖析:从配置加载到参数调优的完整指南
大数据·flink
ha_lydms9 小时前
Window Functions(窗口函数)
大数据·数据仓库·hadoop·spark·数据处理·dataworks·maxcompute
2601_9520477910 小时前
委外入库单同步:旺店通到金蝶云星空的实战配置
大数据·钉钉·制造
阿里云大数据AI技术10 小时前
【云栖实录】一切数据,皆可计算:MaxCompute 升级为AI Native全模态计算服务
大数据·人工智能·agent
珠海西格电力10 小时前
物联网(IoT)在零碳园区中的关键作用:万物互联与数据采集
大数据·人工智能·物联网·安全·系统架构·能源
AI产品测评官10 小时前
2026企业AI招聘选型指南:四类技术路线与硬科技场景适配方案
大数据·人工智能·科技·求职招聘·ai-native
SelectDB技术团队10 小时前
Snowflake 的开源替代怎么选:能力对照、三条部署路径与迁移执行
大数据·数据库·云原生·开源·snowflake·apache doris
Elastic 中国社区官方博客10 小时前
告别繁琐控制台:Kabanos 如何将 MongoDB Compass 的易用性带入 Elasticsearch
大数据·数据库·mongodb·elasticsearch·搜索引擎·全文检索