Data Engineer Case Study 面试:大数据量 ETL 性能优化(Netflix/DataBricks 真题)
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 需要支持:

  1. 高性能处理:日均 PB 级数据处理
  2. 数据倾斜处理:避免热点数据导致性能瓶颈
  3. 资源优化:CPU、内存、存储资源合理利用
  4. 容错机制:任务失败自动重试

关键约束条件

  • 数据量:日均 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 阶段性能瓶颈
  • 内存溢出错误

解决方案

  1. Salting 技术:对热点 key 加盐,分散到多个分区
  2. Broadcast Join:小表广播到大表,避免 Shuffle
  3. 自定义分区:按业务逻辑分区,避免热点
# 数据倾斜处理示例
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. 分区策略优化

分区原则

  • 按查询条件分区
  • 避免过多小文件
  • 平衡分区大小

分区方案

  1. 时间分区:按天/小时分区
  2. 业务分区:按用户 ID、地区等业务维度
  3. 哈希分区:均匀分布数据
# 分区策略示例
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. 缓存策略优化

缓存原则

  • 重复使用的数据缓存
  • 避免缓存大数据集
  • 及时清理无用缓存

缓存方案

  1. Memory 缓存:热点数据缓存到内存
  2. Disk 缓存:大数据集缓存到磁盘
  3. 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 时间

关键技术决策

为什么选择这个方案?

  1. 高性能:优化后的 ETL 处理时间减少 70%
  2. 可扩展性:支持数据量增长
  3. 成本优化:减少计算资源使用
  4. 稳定性:内置容错机制

技术选型对比

方案优势劣势适用场景
Spark高性能运维复杂批量处理
Flink低延迟生态较小实时处理
DataBricks统一管理成本高企业级平台
Salting解决倾斜增加复杂度数据倾斜

面试官追问

常见追问问题

  1. 如果数据量增加 10 倍,架构如何调整?

    • 增加 Spark 执行节点
    • 优化分区策略
    • 增加缓存容量
  2. 如果要求多租户隔离,如何实现?

    • 资源隔离:独立 Spark 集群
    • 数据隔离:按 tenant_id 分区
  3. 如果某个组件宕机,如何保证系统可用性?

    • Spark:容错机制
    • 数据备份:定期备份关键数据
    • 故障转移:自动重试机制

面试技巧

回答框架

  1. 澄清需求:明确业务场景和技术约束
  2. 架构设计:画出架构图,说明每个组件的职责
  3. 技术选型:解释为什么选择某个技术
  4. 权衡分析:讨论方案的优缺点

高分回答要点

  • 数据量级:主动提到日均 PB 级数据
  • 处理延迟:小时级到分钟级
  • 资源成本:优化计算资源使用
  • 容错机制:内置容错机制

本文整理自真实 Data Engineer 面试经验,架构设计经过实际验证。


💡 需要面试辅导?

如果你对准备技术面试感到迷茫,或者想要个性化的面试指导和简历优化,欢迎联系 Interview Coach Pro 获取一对一辅导服务。

👉 联系我们 获取专属面试准备方案

准备好拿下下一次面试了吗?

获取针对你的目标岗位和公司的个性化辅导方案。

联系我们