第4章 环境搭建:Spark + Delta Lake + Kafka集群

说实话,环境搭建这块,看着简单,但坑是真不少。我见过太多人花了两天时间搭环境,最后发现是版本不兼容。所以这一章,咱们把版本、配置、踩坑点一次性说清楚。

4.1 版本兼容性——先看这张表

为什么先讲版本?因为Delta Lake和Kafka的版本匹配,是很多新手翻车的地方。我刚开始用Delta Lake 1.0配Spark 3.0,结果跑起来各种报错,查了半天才发现是API不兼容。

下面这张表,是我在实际项目中验证过的组合,直接照着来就行:

组件 推荐版本 最低版本 备注
Apache Spark 3.3.2 3.2.0 Delta 2.x 必须用 Spark 3.x
Delta Lake 2.3.0 2.0.0 与 Spark 3.3 完美配合
Apache Kafka 3.4.0 3.0.0 建议用 Confluent 发行版
Kafka Connect 3.4.0 3.0.0 与 Kafka 版本一致
Scala 2.12.17 2.12.10 Spark 3.x 默认 Scala 2.12
Java 11 8 推荐 OpenJDK 11
⚠️ 特别注意: Delta Lake 2.0 以上版本不再支持 Spark 2.x。如果你还在用 Spark 2.4,请升级到 Spark 3.x,否则 Delta Lake 跑不起来。

4.2 集群搭建步骤

我个人习惯用 Docker Compose 来搭建测试环境,这样干净、可重复。生产环境当然要用物理机或云集群,但开发阶段,Docker 足够了。

4.2.1 启动 Kafka 集群

先写一个 docker-compose.yml:

version: '3.8'
services:
  zookeeper:
    image: confluentinc/cp-zookeeper:7.4.0
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000

  kafka:
    image: confluentinc/cp-kafka:7.4.0
    depends_on:
      - zookeeper
    ports:
      - "9092:9092"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1

然后执行:

docker-compose up -d

嗯,这里要注意:KAFKA_ADVERTISED_LISTENERS 这个配置,如果你是在容器内访问,要改成容器内地址。我曾经因为没改这个,折腾了半小时连不上。

4.2.2 配置 Spark 与 Delta Lake

Spark 这边,需要把 Delta Lake 的 jar 包加进去。有两种方式:

  1. 启动时指定(推荐开发用)
  2. 放到 Spark 的 jars 目录(生产环境用)

启动命令示例:

spark-shell \
  --packages io.delta:delta-core_2.12:2.3.0 \
  --conf "spark.sql.extensions=io.delta.sql.DeltaSparkSessionExtension" \
  --conf "spark.sql.catalog.spark_catalog=org.apache.spark.sql.delta.catalog.DeltaCatalog"
💡 小技巧: 如果你用 PySpark,记得加上 --conf "spark.sql.adaptive.enabled=false",Delta Lake 在某些场景下和自适应查询有冲突。

4.3 常用配置项详解

配置项这东西,说白了就是「调优」。我刚开始做实时写入时,默认配置跑起来,延迟高得吓人。后来一点点调,才找到感觉。

4.3.1 Delta Lake 核心配置

配置项 默认值 推荐值 说明
spark.databricks.delta.retentionDurationCheck.enabled true false 开发环境关掉,避免频繁报错
spark.databricks.delta.autoCompact.enabled false true 自动合并小文件,写入频繁时建议开启
spark.databricks.delta.optimizeWrite.enabled false true 优化写入布局,减少小文件
spark.sql.adaptive.coalescePartitions.enabled true false 与 Delta 合并操作冲突时关闭

4.3.2 Kafka 生产者配置

实时写入 Kafka,生产者配置是关键。我一般这样配:

# 核心配置
bootstrap.servers=localhost:9092
acks=all
retries=3
batch.size=16384
linger.ms=10
buffer.memory=33554432
key.serializer=org.apache.kafka.common.serialization.StringSerializer
value.serializer=org.apache.kafka.common.serialization.StringSerializer

为什么 acks=all?因为实时写入不能丢数据。虽然延迟会高一点,但数据一致性更重要。你想想看,如果丢了数据,后面查起来多麻烦。

4.3.3 Spark Streaming 与 Kafka 集成配置

用 Structured Streaming 读 Kafka 时,这些配置要记住:

val kafkaParams = Map(
  "kafka.bootstrap.servers" -> "localhost:9092",
  "subscribe" -> "delta-topic",
  "startingOffsets" -> "latest",
  "maxOffsetsPerTrigger" -> "1000",
  "failOnDataLoss" -> "false"
)
🔑 关键点: failOnDataLoss 建议设为 false。为什么?因为 Kafka 日志清理策略可能导致 offset 丢失,设为 true 的话,作业会直接挂掉。我曾经在生产环境吃过这个亏,凌晨三点被电话叫醒……

4.4 整体架构图

下面这张图,把整个环境的关系画清楚了。你看一眼,心里就有数了:

Delta Lake 实时写入 Kafka 环境架构 环境架构总览 数据源(Kafka Topic) Spark Structured Streaming 读取 → 转换 → 写入 Delta Lake 表 ACID 事务 · 版本管理 Kafka Connect Sink Delta → Kafka 实时推送 目标 Kafka Topic 版本匹配 Spark 3.3.2 Delta 2.3.0 Kafka 3.4.0 关键配置 acks=all autoCompact=true failOnDataLoss=false

4.5 验证环境是否正常

环境搭好了,怎么知道能不能用?我一般跑两个测试:

4.5.1 测试 Delta Lake 写入

// 创建 Delta 表并写入数据
val data = spark.range(0, 100).toDF("id")
data.write.format("delta").mode("append").save("/tmp/delta-test")

// 读取验证
val df = spark.read.format("delta").load("/tmp/delta-test")
df.show()

如果能看到 0 到 99 的数据,说明 Delta Lake 没问题。

4.5.2 测试 Kafka 连通性

# 创建测试 topic
kafka-topics --bootstrap-server localhost:9092 --create --topic test-topic --partitions 3 --replication-factor 1

# 生产消息
echo "hello delta" | kafka-console-producer --bootstrap-server localhost:9092 --topic test-topic

# 消费消息
kafka-console-consumer --bootstrap-server localhost:9092 --topic test-topic --from-beginning
💡 验证小技巧: 如果消费端能收到消息,说明 Kafka 集群正常。如果收不到,先检查 KAFKA_ADVERTISED_LISTENERS 配置,这是最常见的坑。

4.6 常见问题与避坑

最后,分享几个我实际踩过的坑:

  • Delta Lake 版本与 Spark 不匹配:Delta 2.x 必须用 Spark 3.x,Delta 1.x 才支持 Spark 2.4。我见过有人用 Delta 2.0 配 Spark 2.4,编译都过不了。
  • Kafka 连接超时:检查防火墙和 advertised.listeners。我曾经在云服务器上部署,忘了配安全组规则,结果一直连不上。
  • Delta 表路径权限:Spark 写 Delta 表时,需要读写权限。如果用的是 HDFS,记得检查目录权限。
  • OOM 问题:如果数据量大,记得调大 spark.executor.memory 和 spark.driver.memory。默认 1G 肯定不够。

环境搭好了,后面的事情就顺了。记住,版本匹配是第一位的,配置调优是第二位的。别急着跑大任务,先把小测试跑通。