4. Spark Streaming 基础:DStream、Receiver、批次间隔与 WordCount 入门案例
在贷后预警场景中,数据以持续流的形式到达(如还款流水、催收记录、逾期状态变更)。Spark Streaming 是构建实时预警管线的核心引擎。本章从最基础的抽象——DStream 出发,讲解数据如何被接收、如何按时间窗口切分,并通过经典的 WordCount 案例串联完整流程。
4.1 DStream:离散化数据流
DStream(Discretized Stream) 是 Spark Streaming 提供的高层抽象,表示一个连续的数据流。从内部实现看,DStream 本质上是一个由 RDD 序列 组成的“流”,每个 RDD 对应一个批次间隔内的数据。
| 概念 | 说明 | 贷后预警类比 |
|---|---|---|
| DStream | 连续数据流的逻辑表示 | “逾期事件流” |
| RDD 序列 | DStream 内部按时间切分的 RDD 集合 | 每 5 秒内的逾期事件快照 |
| 批次间隔 | 将流数据切分为 RDD 的时间窗口 | 预警检查周期(如 5s/10s) |
| 转换操作 | 对 DStream 应用 map/filter/reduceByKey 等 | 过滤逾期金额 > 1000 的事件 |
| 输出操作 | 将结果写入外部系统(HDFS/DB/Kafka) | 写入预警结果表 |
关键理解:DStream 不是“一条一条”处理数据,而是“一批一批”处理。批次间隔决定了实时性的粒度。在贷后预警中,5 秒的批次间隔意味着最长 5 秒的延迟,这对大部分预警场景是可接受的。
4.2 Receiver:数据接收器
Receiver 是 Spark Streaming 从外部数据源拉取数据的组件。每个 Receiver 作为一个长期运行的任务(Task)运行在 Executor 上,负责接收数据并存储到 Spark 的内存中,随后由 Streaming 框架按批次间隔切分为 RDD。
- Receiver 类型:Kafka Receiver、Socket Receiver、File Receiver、Custom Receiver。
- Receiver 数量:可以通过
spark.streaming.blockInterval和并行度控制。 - 可靠性:启用 WAL(Write Ahead Log)时,Receiver 先将数据写入 HDFS 日志,再处理,防止 Driver 重启后数据丢失。
贷后预警注意点:Receiver 的并行度直接影响吞吐量。如果单 Receiver 成为瓶颈,应使用 Kafka Direct 方式(无 Receiver)或增加 Receiver 数量。在预警场景中,建议使用 Kafka Direct API 以获得更好的容错性和背压控制。
4.3 批次间隔(Batch Interval)
批次间隔是 Spark Streaming 的核心时间参数,决定了流数据被切分的粒度。通过 StreamingContext 构造函数或 spark.streaming.batchDuration 配置。
| 批次间隔 | 延迟 | 吞吐量 | 适用场景 |
|---|---|---|---|
| 1 秒 | 低(~1s) | 低 | 高频交易预警、实时风控 |
| 5 秒 | 中(~5s) | 中 | 贷后逾期监控、催收队列 |
| 10 秒 | 较高(~10s) | 高 | 批量报表、非实时预警 |
选择建议:贷后预警通常选择 5 秒作为默认批次间隔。如果数据量极大(如百万级事件/秒),可适当增大到 10 秒,并配合背压(Backpressure)机制防止系统过载。
4.4 WordCount 入门案例:完整流程
以下通过经典的 WordCount 案例,演示 Spark Streaming 从数据接收、批次切分、转换计算到结果输出的完整链路。案例使用 Socket 作为数据源,模拟实时文本流。
4.4.1 案例架构图
4.4.2 完整代码实现
import org.apache.spark.SparkConf
import org.apache.spark.streaming.{Seconds, StreamingContext}
// 1. 创建 StreamingContext,批次间隔 5 秒
val conf = new SparkConf().setAppName("LoanWarningWordCount").setMaster("local[2]")
val ssc = new StreamingContext(conf, Seconds(5))
// 2. 创建 Socket 数据源 DStream(Receiver 方式)
// 连接到本地 9999 端口,模拟实时文本流
val lines: DStream[String] = ssc.socketTextStream("localhost", 9999)
// 3. 转换操作:分词 → 映射为 (word, 1) → 按 key 聚合
val words = lines.flatMap(_.split(" "))
val pairs = words.map(word => (word, 1))
val wordCounts = pairs.reduceByKey(_ + _)
// 4. 输出操作:打印每个批次的结果
wordCounts.print()
// 5. 启动流计算
ssc.start()
ssc.awaitTermination()
4.4.3 执行步骤
- 启动数据源:在终端执行
nc -lk 9999,输入文本行。 - 提交 Spark 应用:运行上述代码,StreamingContext 开始监听 9999 端口。
- 观察输出:每 5 秒打印一次该窗口内的单词计数结果。
4.4.4 数据流与 RDD 切分示意图
4.5 本章小结
- DStream 是 Spark Streaming 的核心抽象,本质是 RDD 序列。
- Receiver 负责数据接入,支持多种数据源,贷后预警推荐 Kafka Direct 方式。
- 批次间隔 决定实时性与吞吐量的平衡,贷后场景默认 5 秒。
- WordCount 案例 完整演示了从 Socket 接收、DStream 转换到结果输出的全流程,是理解 Streaming 编程模型的最佳起点。