Pulsar 与 Apache Spark 的集成 是构建 流批一体数据处理系统 的重要方式。虽然 Spark Streaming 的实时性不如 Flink,但其在 批处理、机器学习、复杂 SQL 分析 方面具有强大生态优势。
通过官方维护的 pulsar-spark-connector,你可以让 Spark Structured Streaming 或 Spark SQL 直接消费 Pulsar 中的实时事件流,或将 Pulsar 作为批处理的数据源/汇(Source/Sink)。
📘 Pulsar 与流处理引擎集成:Apache Spark 详解
一、为什么选择 Pulsar + Spark?
| 场景 | 说明 |
|---|---|
| ✅ 实时 ETL 与数据湖入湖 | Spark Streaming 消费 Pulsar → 写入 Delta Lake / Iceberg |
| ✅ 批流统一处理 | 同一份代码处理实时流与历史数据 |
| ✅ 复杂数据分析 | Spark SQL、DataFrame API 进行聚合、关联 |
| ✅ 机器学习管道 | Spark MLlib 消费实时特征流 |
| ✅ 事件回放分析 | 从任意时间点读取 Pulsar 历史消息进行批处理 |
✅ Pulsar 是“事件源”,Spark 是“分析引擎”
✅ 适合对实时性要求中等(秒级延迟)、但对分析能力要求高的场景。
二、pulsar-spark-connector 核心特性
GitHub 项目:apache/pulsar-spark
1. 支持的 Spark 版本
| Spark 版本 | Connector Artifact |
|---|---|
| Spark 2.4+ | pulsar-spark-connector |
| Spark 3.0+ | 推荐使用 pulsar-sql 或自定义集成 |
⚠️ 注意:
pulsar-spark-connector社区活跃度低于pulsar-flink-connector,部分功能需自行扩展。
2. 支持模式
| 模式 | 说明 |
|---|---|
| ✅ Structured Streaming | 流式消费 Pulsar Topic |
| ✅ Batch Processing | 批量读取 Pulsar 历史消息 |
| ✅ Schema 支持 | JSON、Avro 自动反序列化 |
| ✅ Exactly-Once 语义 | 基于 Checkpoint + Pulsar Cursor |
| ✅ 支持 Event Time | 用于窗口计算 |
三、集成配置与依赖
1. Maven 依赖(Spark 3.x)
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.12</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.pulsar</groupId>
<artifactId>pulsar-spark-connector</artifactId>
<version>3.0.0</version>
</dependency>
或使用
--packages提交作业:spark-submit --packages org.apache.pulsar:pulsar-spark-connector:3.0.0 ...
四、Spark 作为 Pulsar Source(消费消息)
1. Structured Streaming 流式消费
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.functions._
val spark = SparkSession.builder()
.appName("PulsarStructuredStreaming")
.getOrCreate()
import spark.implicits._
// 从 Pulsar 读取流
val df = spark
.readStream
.format("pulsar")
.option("service.url", "pulsar://localhost:6650")
.option("admin.url", "http://localhost:8080")
.option("topic", "persistent://public/default/events")
.option("subscriptionName", "spark-sub")
.load()
// 消息结构:value: Binary, eventTime: Timestamp, key: String, properties: Map
val events = df.select($"value" cast "string" as "text")
// 简单处理:词频统计
val words = events
.withColumn("word", explode(split($"text", " ")))
.groupBy("word")
.count()
// 流式输出(控制台)
val query = words.writeStream
.outputMode("complete")
.format("console")
.start()
query.awaitTermination()
2. 批处理读取历史消息
// 从指定时间开始读取(批处理)
val batchDf = spark
.read
.format("pulsar")
.option("service.url", "pulsar://localhost:6650")
.option("admin.url", "http://localhost:8080")
.option("topic", "persistent://public/default/events")
.option("startingOffsets", "earliest") // 或 "latest", "2024-01-01T00:00:00Z"
.load()
batchDf.show()
✅ 适用于数据修复、审计、离线分析。
五、Spark 作为 Pulsar Sink(写入消息)
1. 将处理结果写回 Pulsar
// 假设 processedDf 是处理后的 DataFrame
val processedDf = words.select(to_json(struct($"word", $"count")) as "value")
// 写入 Pulsar
processedDf.writeStream
.format("pulsar")
.option("service.url", "pulsar://localhost:6650")
.option("admin.url", "http://localhost:8080")
.option("topic", "persistent://public/default/word-count")
.outputMode("update") // append / update / complete
.start()
.awaitTermination()
六、Schema 支持与数据类型映射
Pulsar 消息字段在 Spark 中的映射:
| Pulsar 字段 | Spark SQL 类型 | 说明 |
|---|---|---|
value | BINARY | 原始字节,可转换为 STRING/JSON |
eventTime | TIMESTAMP | 用于事件时间窗口 |
publishTime | TIMESTAMP | Broker 接收时间 |
key | STRING | 消息 Key |
properties | MAP<STRING, STRING> | 自定义属性 |
使用 JSON Schema 自动解析
val parsed = df.select(
from_json($"value" cast "string", schema).as("data")
).select("data.*")
七、Exactly-Once 语义实现
- 基于 Checkpoint:Spark Streaming 将消费位点(Cursor)保存在 Checkpoint 中。
- 幂等写入:Sink 写入 Pulsar 时建议启用去重(Pulsar Producer Deduplication)。
- 端到端 Exactly-Once:
- Spark Checkpoint + Pulsar Cursor 恢复
- 结合幂等 Sink 实现
// 启用 Checkpoint
val query = words.writeStream
.option("checkpointLocation", "/tmp/checkpoint")
...
⚠️ 注意:Pulsar Spark Connector 不支持事务写入,需业务侧保证幂等。
八、部署方式
| 方式 | 说明 |
|---|---|
| Spark Standalone | 独立集群,简单 |
| Spark on YARN | 企业常用,资源调度好 |
| Spark on Kubernetes | 云原生部署 |
| Databricks / EMR | 云平台托管服务 |
✅ 推荐生产环境使用 Spark on K8s 或 Databricks。
九、性能调优建议
| 优化点 | 建议 |
|---|---|
| ✅ 合理设置批间隔 | trigger(ProcessingTime("10 seconds")) |
| ✅ 并行度匹配 | Spark 分区数 ≈ Pulsar 分区数 |
| ✅ 启用 Kryo 序列化 | 提升性能 |
| ✅ 压缩 | Pulsar Producer 启用 LZ4/ZSTD |
| ✅ 状态清理 | 设置 spark.sql.streaming.stateStore.stateSchemaCheck |
| ✅ 监控 | 集成 Prometheus + Grafana |
十、与 Flink 的对比
| 特性 | Spark | Flink |
|---|---|---|
| 实时性 | 秒级(微批) | 毫秒级(流原生) |
| 状态管理 | RocksDB / 内存 | 高性能状态后端 |
| 窗口计算 | 支持 | 更灵活 |
| SQL 支持 | ✅ 极强 | ✅ 强 |
| 机器学习 | ✅ Spark MLlib | ❌ 弱 |
| 社区活跃度 | 高 | 高 |
| Connector 成熟度 | 中等 | 高(pulsar-flink-connector) |
✅ 选型建议:
- 实时性要求高 → Flink
- 分析/ML 要求高 → Spark
✅ 总结
| 特性 | 说明 |
|---|---|
| ✅ 流批统一 | 同一套 API 处理实时与历史数据 |
| ✅ SQL 友好 | Spark SQL 强大分析能力 |
| ✅ 机器学习集成 | MLlib 天然支持 |
| ✅ 事件回放 | 从任意时间点读取 Pulsar 消息 |
| ⚠️ 实时性中等 | 微批模式,延迟秒级 |
| ⚠️ Connector 成熟度 | 不如 Flink 生态 |
📌 一句话总结:
Pulsar + Spark = 实时分析的“数据大脑” —— 通过
pulsar-spark-connector,你可以将 Pulsar 的实时事件流接入 Spark 的强大分析生态,实现从流式 ETL 到机器学习的完整闭环。
538

被折叠的 条评论
为什么被折叠?



