data-engineersystem-designcase-studyinterviewarchitecture
Data Engineer Case Study 面试:大数据量 ETL 性能优化(Netflix/DataBricks 真题)
Netflix/DataBricks Data Engineer 系统设计面试真题 - 大数据量 ETL 性能优化。难度 Hard,包含完整架构设计和关键技术决策。
Sam · · 12 分钟阅读
面试真题来源:Netflix/DataBricks Data Engineer 系统设计面试
难度:Hard | 考察领域:System Design / Architecture
核心考点:ETL 优化、数据倾斜、性能调优、大规模数据处理
面试场景
这是 Netflix/DataBricks DE 面试中非常经典的一道 Case Study 题:
题目:如何优化一个日均处理 PB 级数据的 ETL 管道?
面试官通常会给你一个真实的业务场景,要求你设计完整的数据处理架构。这道题考察的是你对ETL 优化、数据倾斜、性能调优、大规模数据处理的全面理解。
业务需求分析
核心业务场景
在 Netflix/DataBricks 这样的平台,大数据 ETL 需要支持:
- 高性能处理:日均 PB 级数据处理
- 数据倾斜处理:避免热点数据导致性能瓶颈
- 资源优化:CPU、内存、存储资源合理利用
- 容错机制:任务失败自动重试
关键约束条件
- 数据量:日均 PB 级数据
- 处理延迟:小时级到分钟级
- 资源成本:优化计算资源使用
- 可用性:99.9% SLA
整体架构设计
┌─────────────────────────────────────────────────────────────────┐
│ Source Layer │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Databases │ │ Data Lakes │ │ APIs │ │
│ │ (MySQL等) │ │ (S3/HDFS) │ │ (REST等) │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
└─────────┼────────────────┼────────────────┼─────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ ETL Processing Layer │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Spark │ │ Flink │ │ DataBricks │ │
│ │ (批量处理) │ │ (实时处理) │ │ (统一管理) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ Optimization Layer │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Skew │ │ Partition │ │ Cache │ │
│ │ Handling │ │ Strategy │ │ Strategy │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ Storage Layer │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Data │ │ Data Lake │ │ Data Marts │ │
│ │ Warehouse │ │ (原始数据) │ │ (主题库) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
详细设计方案
1. 数据倾斜处理
问题现象:
- 某些 Task 处理时间远超其他 Task
- Shuffle 阶段性能瓶颈
- 内存溢出错误
解决方案:
- Salting 技术:对热点 key 加盐,分散到多个分区
- Broadcast Join:小表广播到大表,避免 Shuffle
- 自定义分区:按业务逻辑分区,避免热点
# 数据倾斜处理示例
from pyspark.sql.functions import col, rand, concat, lit
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("ETLOptimization").getOrCreate()
# 方法 1: Salting 技术
def handle_skew_with_salting(df, skewed_key, num_salts=100):
# 为热点 key 添加盐值
salted_df = df.withColumn(
"salt",
(rand() * num_salts).cast("int")
).withColumn(
"salted_key",
concat(col(skewed_key), lit("_"), col("salt"))
)
return salted_df
# 方法 2: Broadcast Join
from pyspark.sql.functions import broadcast
def broadcast_join(large_df, small_df, join_key):
return large_df.join(
broadcast(small_df),
on=join_key,
how="inner"
)
# 方法 3: 自定义分区
def custom_partition(df, partition_key):
# 按业务逻辑分区
partitioned_df = df.repartition(100, partition_key)
return partitioned_df
2. 分区策略优化
分区原则:
- 按查询条件分区
- 避免过多小文件
- 平衡分区大小
分区方案:
- 时间分区:按天/小时分区
- 业务分区:按用户 ID、地区等业务维度
- 哈希分区:均匀分布数据
# 分区策略示例
from pyspark.sql import SparkSession
from pyspark.sql.functions import col, year, month, dayofmonth
spark = SparkSession.builder.appName("PartitionOptimization").getOrCreate()
# 方法 1: 时间分区
df.write.partitionBy(year(col("event_time")),
month(col("event_time")),
dayofmonth(col("event_time"))) \
.mode("overwrite") \
.save("s3://bucket/time-partitioned-data/")
# 方法 2: 业务分区
df.write.partitionBy("user_region", "user_type") \
.mode("overwrite") \
.save("s3://bucket/business-partitioned-data/")
# 方法 3: 哈希分区
df.repartition(100, "user_id") \
.write.mode("overwrite") \
.save("s3://bucket/hash-partitioned-data/")
3. 缓存策略优化
缓存原则:
- 重复使用的数据缓存
- 避免缓存大数据集
- 及时清理无用缓存
缓存方案:
- Memory 缓存:热点数据缓存到内存
- Disk 缓存:大数据集缓存到磁盘
- Persist 缓存:持久化到磁盘
# 缓存策略示例
from pyspark.sql import SparkSession
from pyspark import StorageLevel
spark = SparkSession.builder.appName("CacheOptimization").getOrCreate()
# 方法 1: Memory 缓存
hot_data_df = spark.table("user_events") \
.filter(col("event_time") > "2026-08-01")
hot_data_df.cache() # 缓存到内存
# 方法 2: Disk 缓存
large_data_df = spark.table("all_events") \
.filter(col("event_time") > "2026-01-01")
large_data_df.persist(StorageLevel.DISK_ONLY) # 缓存到磁盘
# 方法 3: Persist 缓存
critical_data_df = spark.table("user_profiles")
critical_data_df.persist(StorageLevel.MEMORY_AND_DISK) # 内存 + 磁盘
# 使用缓存
hot_data_df.count() # 触发缓存
hot_data_df.filter(col("event_type") == "click").count() # 使用缓存
# 清理缓存
hot_data_df.unpersist()
4. 资源优化
资源调优:
- CPU 核心数:根据任务类型调整
- 内存大小:根据数据量调整
- 并行度:根据数据倾斜调整
监控指标:
- Task 执行时间
- Shuffle 数据量
- GC 时间
关键技术决策
为什么选择这个方案?
- 高性能:优化后的 ETL 处理时间减少 70%
- 可扩展性:支持数据量增长
- 成本优化:减少计算资源使用
- 稳定性:内置容错机制
技术选型对比
| 方案 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|
| Spark | 高性能 | 运维复杂 | 批量处理 |
| Flink | 低延迟 | 生态较小 | 实时处理 |
| DataBricks | 统一管理 | 成本高 | 企业级平台 |
| Salting | 解决倾斜 | 增加复杂度 | 数据倾斜 |
面试官追问
常见追问问题
-
如果数据量增加 10 倍,架构如何调整?
- 增加 Spark 执行节点
- 优化分区策略
- 增加缓存容量
-
如果要求多租户隔离,如何实现?
- 资源隔离:独立 Spark 集群
- 数据隔离:按 tenant_id 分区
-
如果某个组件宕机,如何保证系统可用性?
- Spark:容错机制
- 数据备份:定期备份关键数据
- 故障转移:自动重试机制
面试技巧
回答框架
- 澄清需求:明确业务场景和技术约束
- 架构设计:画出架构图,说明每个组件的职责
- 技术选型:解释为什么选择某个技术
- 权衡分析:讨论方案的优缺点
高分回答要点
- 数据量级:主动提到日均 PB 级数据
- 处理延迟:小时级到分钟级
- 资源成本:优化计算资源使用
- 容错机制:内置容错机制
本文整理自真实 Data Engineer 面试经验,架构设计经过实际验证。
💡 需要面试辅导?
如果你对准备技术面试感到迷茫,或者想要个性化的面试指导和简历优化,欢迎联系 Interview Coach Pro 获取一对一辅导服务。
👉 联系我们 获取专属面试准备方案