Spark Structured Streaming的核心概念:输入源(Sources)、输出接收器(Sinks) 和 输出模式(Output Modes)

Structured Streaming 的核心概念,重点关注其模块化设计:输入源(Sources)输出接收器(Sinks)输出模式(Output Modes)

Structured Streaming 核心理念:

Structured Streaming 是 Apache Spark 提供的声明式、可扩展且容错的流处理引擎。它将无限数据流视为一个不断追加数据的无界表(Unbounded Table)。流计算被表达为作用在这个表上的标准批处理查询(Batch-like Query)。引擎在底层负责将这个查询连续地、增量地应用到新到达的数据上,并将结果更新到最终的结果表(Result Table)。用户指定如何将结果表的内容输出到外部存储(即 Sink)以及输出的频率(Trigger)和方式(Output Mode)。

现在聚焦到三大核心概念:

1. 输入源

输入源定义了流处理查询的数据入口。Structured Streaming 内置支持多种常见的数据源,并可以通过 API 扩展自定义源。

  • 核心内置源:

    • 文件源:
      • 格式: 支持读取目录中的文本文件、CSV、JSON、Parquet、ORC 等格式。
      • 行为: 监听指定目录,将目录中新出现的文件或现有文件中新追加的内容视为流数据。
      • 特点: 简单易用,适合将文件系统作为数据采集的落地点。支持 latestFirst 选项控制是否优先处理新文件。
    • Kafka 源:
      • 格式: 从 Apache Kafka 主题读取数据,支持 Kafka 0.10+。
      • 行为: 订阅一个或多个 Kafka 主题(或主题分区)。数据以键值对(Key-Value)的形式表示,通常 Value 是包含实际数据的字节数组或字符串,需要用户后续解析(如 JSON)。
      • 特点: 生产环境最常用,提供高吞吐、低延迟、可扩展的消息传递。原生支持精确一次语义(需要配合 Kafka 0.11+ 和 Structured Streaming 的检查点)。
    • Socket 源:
      • 格式: 从网络 Socket 连接读取 UTF8 文本数据。
      • 行为: 连接到指定的主机名和端口,将接收到的每一行文本视为一条记录。
      • 特点: 主要用于测试和演示不提供容错保证,不适合生产环境(因为无法重放丢失的数据)。
    • 速率源:
      • 格式: 由 Structured Streaming 引擎自身生成测试数据。
      • 行为: 每秒生成指定行数的数据。每行包含两个字段:timestamp(时间戳)和 value(一个自增的长整型)。
      • 特点: 专用于测试、基准测试和教学。方便控制数据生成速率和总量。
  • 关键属性:

    • Schema: 大部分源(如 Kafka, 文件)需要或强烈建议用户提供数据的 Schema(结构信息)。引擎依赖 Schema 进行类型安全检查和优化。Kafka 的 Value 通常需要用户指定 Schema 来解析。
    • 容错: 容错能力取决于源本身。Kafka(配合检查点)支持精确一次;文件源支持精确一次(通过记录已处理的文件列表);Socket 和 Rate 源不支持容错。
    • 分区: 像 Kafka 这样的源天然支持分区读取,Spark 可以并行处理不同分区的数据。

2. 输出接收器

输出接收器定义了处理后的结果(即结果表的内容)写入到哪里以及如何写入。和源一样,Structured Streaming 提供了多种内置 Sink 并支持自定义。

  • 核心内置接收器:

    • 文件接收器:
      • 格式: 将结果写入到文件系统目录,支持文本、CSV、JSON、Parquet、ORC 等格式。
      • 行为: 将每个微批次(或连续处理周期)的结果写入到指定目录下的新文件中。文件名通常包含时间戳等信息。
      • 特点: 适用于将处理结果存档或供下游批处理系统(如 Hive)消费。仅支持 Append 输出模式
    • Kafka 接收器:
      • 格式: 将结果作为消息写入一个或多个 Apache Kafka 主题。
      • 行为: 结果集中的每一行会被转换为一条 Kafka 记录。用户需要指定行中的哪些列作为 Kafka 的 Key 和 Value(通常 Value 是整行的 JSON 序列化或特定列)。
      • 特点: 生产环境常用,将处理结果流式传输给下游消费者。支持 Append 和 Update 模式。配合 Kafka 0.11+ 和检查点可支持精确一次写入。
    • 控制台接收器:
      • 格式: 将结果输出到驱动程序(Driver)的标准输出(stdout)或标准错误(stderr)。
      • 行为: 每个触发间隔(微批次)结束后,将该批次的结果打印到控制台。
      • 特点: 主要用于开发和调试。支持 Append 和 Update 模式(Complete 模式在控制台输出所有数据可能不实用)。生产环境避免使用
    • 内存接收器:
      • 格式: 将结果作为内存中的表存储在驱动程序中。
      • 行为: 每个触发间隔后更新内存表的内容(根据输出模式)。
      • 特点: 主要用于交互式查询和调试(可以通过 spark.table() 查询内存表)。支持 Append 和 Complete 模式(Update 模式在内存中意义不大)。不适合大数据量或生产环境
    • Foreach 接收器:
      • 格式: 最灵活的自定义接收器接口
      • 行为: 对输出结果集中的每一行记录,执行用户自定义的写入逻辑。用户需要实现 ForeachWriter 接口,定义 open, process, close 方法,在其中编写连接目标系统、写入单行数据、处理错误、管理事务等逻辑。
      • 特点: 用于写入任何没有内置支持的外部系统(如数据库:MySQL, PostgreSQL, Cassandra, HBase; NoSQL; 键值存储; 自定义 API 等)。输出模式由用户逻辑实现决定实现精确一次语义需要用户在 ForeachWriter 中利用批次 ID 或事务机制
  • 关键属性:

    • 输出模式兼容性: 不同的 Sink 只支持特定的输出模式(见下文输出模式部分)。例如,File Sink 只支持 Append,而 Console Sink 支持 Append 和 Update
    • 容错语义: Sink 对容错语义(精确一次)的支持程度各异。内置 Sink 如 Kafka(0.11+)和 File 在启用检查点时支持精确一次。Foreach Sink 的精确一次需要用户自己实现(利用事务或幂等写入)。
    • 触发后输出: Sink 的写入操作发生在每个触发间隔(Trigger) 结束时。

3. 输出模式

输出模式定义了每次触发计算后,结果表的哪些变更(Changes)应该写入到 Sink。这是 Structured Streaming 非常核心的概念,直接决定了 Sink 能看到什么样的结果。

  • 三种主要模式:

    • Append 模式:
      • 含义: 只将结果表中自上次触发以来新追加的行写入到 Sink。
      • 要求: 查询必须保证结果表中的行是不可变的(Immutable),即一旦输出,该行在后续触发中不会被修改或删除。聚合查询通常需要搭配 Watermark 使用 Append 模式来输出最终确定的聚合结果
      • 典型场景:
        • 无状态查询(如 select, filter, map)。
        • 使用 Watermark 的基于事件时间的聚合(如 groupBy().agg() + Watermark)。Watermark 确保了“迟到数据”不会影响已输出的聚合结果。
      • Sink 支持: 文件、控制台、Kafka、内存(作为新行追加)、Foreach(取决于实现)。
    • Update 模式:
      • 含义: 只将结果表中自上次触发以来发生更新(修改)的行写入到 Sink。未更改的行和已删除的行不会输出
      • 行为: 如果某行是本次触发中第一次出现的,它被视为“更新”(插入)。如果某行之前存在但在本次触发中被修改了值,它也会作为更新输出(包含新值)。
      • 典型场景:
        • 带状态的聚合查询(无论是否使用 Watermark),并且你关心聚合值的每次变化(如实时仪表盘)。
        • 使用 mapGroupsWithStateflatMapGroupsWithState 的自定义有状态处理。
        • dropDuplicates() 去重操作。
      • Sink 支持: 控制台、Kafka、内存(更新现有行)、Foreach(取决于实现)。文件 Sink 不支持!
    • Complete 模式:
      • 含义: 每次触发后,将整个更新后的结果表全部内容写入到 Sink。
      • 要求: 结果表必须是有界的,或者查询本身维护的状态是有限且可管理的。通常意味着查询必须是聚合操作groupBy().agg(), count() 等),因为聚合的结果集大小通常远小于原始数据流,并且随着时间推移不会无限增长(或增长可控)。无状态查询或产生无界结果集的查询(如 select不能使用 Complete 模式
      • 典型场景:
        • 需要看到迄今为止所有数据的完整聚合结果(如全局计数、总和、TopN)。
        • 结果集相对较小的情况。
      • Sink 支持: 内存、控制台(对小数据集调试)、Foreach(取决于实现)。文件 Sink 和 Kafka Sink 不支持直接写入整个表!(通常需要借助 Foreach 或其他机制间接实现类似效果)。
  • 关键点:

    • 模式与查询的兼容性: 不是所有查询都支持所有输出模式。例如:
      • select ... where ...(无状态)支持 Append, Update。
      • groupBy().count()(有状态聚合)支持 Update, Complete (如果状态可管理)。
      • groupBy().count() + Watermark 支持 Append (输出最终结果), Update (输出每次变化)。
    • 模式与 Sink 的兼容性: 每种 Sink 只支持特定的模式(见上述描述)。
    • Watermark 的作用: Watermark 主要与 Append 模式结合使用,用于处理迟到数据并安全地输出最终确定的聚合结果。在 Update 模式中,Watermark 主要影响状态清理,不影响输出哪些行(所有更新都会输出)。
    • 结果表视图: 输出模式定义了 Sink 看到的结果表的“视图”是增量变更(Append, Update)还是全量快照(Complete)。

总结与关联:

  1. 声明式查询: 用户编写一个静态的 DataFrame/Dataset/SQL 查询,就像处理批数据一样。
  2. 输入源 (Source): 指定这个查询从哪里读取流数据(Kafka, Files, etc.)。
  3. 输出模式 (Output Mode): 定义每次触发计算后,查询产生的结果表的哪些变更(新行、更新行、整个表)是用户感兴趣的,需要输出。
  4. 输出接收器 (Sink): 指定将 Output Mode 定义的变更写入到哪里(Console, Kafka, Files, Database via Foreach, etc.)。
  5. 触发器 (Trigger): 控制何时执行计算并输出结果(默认按微批次处理可用数据,也可配置固定间隔、连续模式或一次性触发)。

选择指南:

  • 选择 Source: 根据数据来源(Kafka 实时管道?文件归档?测试数据?)。
  • 选择 Sink: 根据结果去向(写回 Kafka 供下游消费?存文件供分析?调试输出?写数据库?)。
  • 选择 Output Mode
    • 需要最终确定的结果(且不关心中间变化)-> Append (通常需 Watermark)。
    • 需要实时看到聚合结果的每一次变化 -> Update
    • 需要每次看到完整的最新聚合结果(且结果集小)-> Complete
    • 必须确保选择的 Output Mode 同时兼容你的查询逻辑和选定的 Sink!

理解 Source、Sink 和 Output Mode 的交互是高效、正确使用 Structured Streaming 构建流处理应用的关键。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值