- Authors

- Name
- Youngju Kim
- @fjvbn20031
目录
- 数据工程概述
- Apache Spark
- Apache Kafka
- Apache Airflow
- dbt (Data Build Tool)
- Delta Lake / Apache Iceberg
- 特征存储
- 数据质量与监控
- 云数据平台
- 测验
数据工程概述
数据工程是 AI/ML 系统的根基所在。设计并构建数据流水线,将数据以适合分析与模型训练的形式提供出来,是其核心角色。
角色对比:数据工程师 vs 数据科学家 vs ML 工程师
| 角色 | 主要职责 | 核心工具 |
|---|---|---|
| 数据工程师 | 构建流水线、管理数据存储 | Spark, Kafka, Airflow, dbt |
| 数据科学家 | 数据分析、模型开发 | Python, Jupyter, Pandas, Scikit-learn |
| ML 工程师 | 模型部署、服务基础设施 | MLflow, Kubeflow, TFX, Ray |
现代数据栈架构
现代数据栈(Modern Data Stack)已经转向以云为中心重构:
- 采集(Ingestion):Fivetran、Airbyte、Kafka
- 存储(Storage):Snowflake、BigQuery、Redshift、Delta Lake
- 转换(Transformation):dbt、Spark、Beam
- 编排(Orchestration):Airflow、Prefect、Dagster
- 可视化(Visualization):Tableau、Looker、Metabase
批处理 vs 流处理
批处理(Batch Processing)按周期处理大批量数据。用于数据仓库 ETL 作业、日报生成、模型再训练等场景。
流处理(Stream Processing)在数据生成的同时立即处理。适合实时欺诈检测、异常检测、推荐系统更新等场景。
Lambda 架构 vs Kappa 架构
Lambda 架构并行运行批处理层与速度层,将精确的批处理结果与实时流结果在服务层合并。复杂度较高,但能保证准确性。
Kappa 架构只用流处理层来简化架构。随着 Kafka Streams、Flink 等工具的发展,它已成为一个实用的选择。易于维护,也能保持代码库的一致性。
Apache Spark
Apache Spark 是面向大规模数据处理的统一分析引擎。凭借内存中处理,性能最高可达 Hadoop MapReduce 的 100 倍。
Spark 架构
Spark 集群由三个核心组件构成:
- Driver:运行 SparkContext 并协调作业的主进程
- Executor:实际执行数据处理的工作进程
- Cluster Manager:YARN、Kubernetes、Mesos 或 Spark Standalone
RDD、DataFrame、Dataset API
RDD(Resilient Distributed Dataset)是 Spark 的基本数据结构,为分布式集合提供不可变操作。
DataFrame 是带 schema 的分布式集合,提供类似 SQL 的 API。借助 Catalyst 优化器自动优化查询。
Dataset 是 DataFrame 的类型安全版本,在 Scala/Java 中支持编译期类型检查。
用 PySpark 做 AI 特征工程
from pyspark.sql import SparkSession
from pyspark.sql.functions import col, count, avg, when
from pyspark.ml.feature import VectorAssembler
from pyspark.ml.classification import RandomForestClassifier
spark = SparkSession.builder \
.appName("AI Feature Engineering") \
.config("spark.sql.adaptive.enabled", "true") \
.getOrCreate()
# 加载并转换数据
df = spark.read.parquet("s3://data-lake/features/")
df_clean = df.dropna() \
.withColumn("age_group", when(col("age") < 30, "young")
.when(col("age") < 50, "middle")
.otherwise("senior"))
# 聚合统计
stats_df = df_clean.groupBy("category").agg(
count("*").alias("cnt"),
avg("score").alias("avg_score")
)
# 构建特征向量
assembler = VectorAssembler(
inputCols=["age", "income", "score"],
outputCol="features"
)
ml_df = assembler.transform(df_clean)
# 训练模型
rf = RandomForestClassifier(numTrees=100, featuresCol="features")
model = rf.fit(ml_df)
Spark SQL 优化技巧
- 分区(Partitioning):按经常过滤的列做分区。
- 广播 Join(Broadcast Join):小表使用广播 join。
- 缓存(Caching):反复使用的 DataFrame 用
cache()或persist()保留在内存中。 - AQE(Adaptive Query Execution):利用 Spark 3.0+ 的动态查询优化。
Apache Kafka
Apache Kafka 是一个高吞吐、具备容错能力的分布式事件流平台。由 LinkedIn 开发并开源,现已成为实时 AI 流水线的核心基础设施。
Kafka 架构
- Broker:存储并转发消息的服务器。集群由多个 Broker 组成。
- Topic:消息发布所在的分类/信息流名称
- Partition:将 Topic 切分以实现并行处理。每个分区保证顺序。
- Consumer Group:共享同一 Topic 的消费者集合,提供负载均衡。
- Offset:分区内消息的唯一位置标识符
生产者/消费者模式
from kafka import KafkaProducer, KafkaConsumer
import json
import numpy as np
# 生产者:发送实时特征数据
producer = KafkaProducer(
bootstrap_servers=['localhost:9092'],
value_serializer=lambda v: json.dumps(v).encode('utf-8')
)
def send_feature(data):
producer.send('ml-features', value={
'timestamp': data['ts'],
'features': data['features'].tolist(),
'user_id': data['user_id']
})
# 消费者:实时 AI 推理
consumer = KafkaConsumer(
'ml-features',
bootstrap_servers=['localhost:9092'],
value_deserializer=lambda m: json.loads(m.decode('utf-8'))
)
import onnxruntime as ort
session = ort.InferenceSession('model.onnx')
for msg in consumer:
features = np.array(msg.value['features']).reshape(1, -1)
prediction = session.run(None, {'input': features.astype(np.float32)})[0]
print(f"User {msg.value['user_id']}: {prediction}")
Kafka Streams 与 ksqlDB
Kafka Streams 是一个 Java/Scala 库,支持从 Kafka Topic 读取、转换后再写回 Kafka 的流处理。ksqlDB 是一个事件流数据库,让你能用 SQL 编写流式查询。
Kafka 在实时 AI 流水线中的角色:
- 事件源(用户行为、传感器数据等)
- 传递特征工程结果
- 发布模型预测结果
- 收集 A/B 测试结果
Apache Airflow
Apache Airflow 是一个以编程方式定义、调度、监控流水线的工作流管理平台。
DAG(有向无环图)概念
DAG 是有方向且无环的图,是 Airflow 中表示工作流的方式。每个节点是一个 Task,边表示依赖关系(执行顺序)。
Operator 类型
- PythonOperator:执行 Python 函数
- BashOperator:执行 shell 命令
- SQLExecuteQueryOperator:执行 SQL 查询
- KubernetesPodOperator:运行 Kubernetes Pod
- SparkSubmitOperator:提交 Spark 作业
用 TaskFlow API 构建 ML 流水线
from airflow.decorators import dag, task
from datetime import datetime
@dag(schedule='@daily', start_date=datetime(2026, 1, 1))
def ml_training_pipeline():
@task
def extract_data():
# 提取数据
return {'rows': 10000, 'path': '/tmp/data.parquet'}
@task
def preprocess(info: dict):
# 预处理
import pandas as pd
df = pd.read_parquet(info['path'])
df_clean = df.dropna()
return df_clean.to_dict()
@task
def train_model(data: dict):
# 模型训练
from sklearn.ensemble import GradientBoostingClassifier
import mlflow
with mlflow.start_run():
model = GradientBoostingClassifier()
# training logic here
mlflow.sklearn.log_model(model, "model")
return "model_trained"
@task
def validate_model(status: str):
# 模型验证
if status == "model_trained":
return {"accuracy": 0.92, "passed": True}
return {"passed": False}
raw = extract_data()
processed = preprocess(raw)
result = train_model(processed)
validate_model(result)
dag_instance = ml_training_pipeline()
Airflow 最佳实践
- 幂等性(Idempotency):同一个 DAG 无论运行多少次,结果都应保持一致。
- 原子性(Atomicity):Task 要么完全成功,要么完全失败。
- 减少 XCom 使用:大数据量应使用外部存储,而不是 XCom。
- 设置 SLA:为关键流水线设置 SLA(Service Level Agreement)。
dbt (Data Build Tool)
dbt 让分析工程师能够用 SQL 编写数据转换逻辑,并内置版本管理、测试与文档化能力。
dbt 的角色与 ELT 模式
与传统的 ETL(Extract-Transform-Load)不同,dbt 采用 ELT(Extract-Load-Transform)模式。先把原始数据加载进数据仓库,再在仓库内部用 SQL 完成转换。
模型分层结构
models/
├── staging/ # 清洗原始源数据
│ ├── stg_orders.sql
│ └── stg_customers.sql
├── intermediate/ # 业务逻辑的中间转换
│ └── int_order_items.sql
└── marts/ # 面向最终业务的表
├── fct_orders.sql
└── dim_customers.sql
Jinja 模板与 ref() 函数
dbt 使用 Jinja 模板引擎,为 SQL 添加动态能力:
-- models/marts/fct_orders.sql
SELECT
o.order_id,
o.customer_id,
c.customer_name,
o.total_amount,
o.created_at
FROM {{ ref('stg_orders') }} o
LEFT JOIN {{ ref('dim_customers') }} c
ON o.customer_id = c.customer_id
WHERE o.status = 'completed'
ref() 函数会自动推断模型间的依赖关系,并按正确的顺序执行。
数据测试与文档化
# schema.yml
models:
- name: fct_orders
description: '已完成订单事实表'
columns:
- name: order_id
description: '订单唯一 ID'
tests:
- unique
- not_null
- name: total_amount
tests:
- not_null
- dbt_utils.accepted_range:
min_value: 0
Delta Lake / Apache Iceberg
Delta Lake 与 Apache Iceberg 是为数据湖带来 ACID 事务能力的开放表格式。
核心功能
- ACID 事务:在并发读写下保证数据一致性
- 时间旅行(Time Travel):可以查询特定时间点的数据快照
- 模式演进(Schema Evolution):在不破坏既有数据的前提下变更 schema
- 数据版本管理:追踪变更历史并支持回滚
Delta Lake 的 Merge/Upsert 操作
from delta.tables import DeltaTable
from pyspark.sql import SparkSession
spark = SparkSession.builder \
.config("spark.sql.extensions", "io.delta.sql.DeltaSparkSessionExtension") \
.config("spark.sql.catalog.spark_catalog",
"org.apache.spark.sql.delta.catalog.DeltaCatalog") \
.getOrCreate()
# Upsert (Merge) 操作
delta_table = DeltaTable.forPath(spark, "/delta/users")
updates_df = spark.read.parquet("/tmp/updates/")
delta_table.alias("target").merge(
updates_df.alias("source"),
"target.user_id = source.user_id"
).whenMatchedUpdateAll() \
.whenNotMatchedInsertAll() \
.execute()
# 时间旅行:查询昨天的数据
df_yesterday = spark.read.format("delta") \
.option("timestampAsOf", "2026-03-16") \
.load("/delta/users")
# 按版本查询
df_v1 = spark.read.format("delta") \
.option("versionAsOf", 1) \
.load("/delta/users")
# 查看变更历史
delta_table.history().show()
Z-Order 聚簇
Z-Order 把相关数据放在同一批文件中,以此提升查询性能:
spark.sql("""
OPTIMIZE delta.`/delta/events`
ZORDER BY (user_id, event_date)
""")
特征存储
特征存储是集中管理 ML 特征的存储系统,用于保证特征的复用性、一致性与治理。
在线 vs 离线特征存储
离线特征存储保存用于模型训练的大规模历史特征,以 Parquet、Delta Lake 格式存放在数据湖中。
在线特征存储以低延迟提供用于实时推理的最新特征,存放在 Redis、DynamoDB、Cassandra 等内存/NoSQL 数据库中。
Feast(开源特征存储)
from feast import FeatureStore, Entity, FeatureView, Field
from feast.types import Float32, Int64
# 定义特征
user_stats = FeatureView(
name="user_stats",
entities=["user_id"],
schema=[
Field(name="avg_purchase_amount", dtype=Float32),
Field(name="purchase_count_30d", dtype=Int64),
],
ttl=timedelta(days=30),
)
# 在线特征查询(实时推理)
store = FeatureStore(repo_path=".")
features = store.get_online_features(
features=["user_stats:avg_purchase_amount", "user_stats:purchase_count_30d"],
entity_rows=[{"user_id": 1001}],
).to_dict()
托管式特征存储
- Tecton:企业级特征平台,支持实时转换
- Vertex AI Feature Store:GCP 集成托管服务
- SageMaker Feature Store:AWS 集成托管服务
- Databricks Feature Store:基于 Delta Lake 的特征管理
数据质量与监控
数据质量决定了 AI 系统的可靠性。"Garbage in, garbage out" 在 ML 中尤其重要。
用 Great Expectations 做数据校验
Great Expectations 是一个为数据流水线添加自动化数据校验的工具:
import great_expectations as gx
context = gx.get_context()
datasource = context.sources.add_pandas("my_datasource")
# 定义期望(Expectation)
suite = context.add_expectation_suite("orders_suite")
validator = context.get_validator(
batch_request=batch_request,
expectation_suite_name="orders_suite"
)
validator.expect_column_values_to_not_be_null("order_id")
validator.expect_column_values_to_be_between("total_amount", min_value=0, max_value=100000)
validator.expect_column_values_to_be_unique("order_id")
validator.save_expectation_suite()
# 执行校验
checkpoint = context.add_or_update_checkpoint(
name="orders_checkpoint",
validations=[{"batch_request": batch_request, "expectation_suite_name": "orders_suite"}],
)
result = checkpoint.run()
数据漂移检测
数据漂移(Data Drift)是生产数据的统计特性偏离训练数据的现象。可以用 Evidently AI、WhyLogs、Nannyml 等工具检测:
from evidently.report import Report
from evidently.metric_preset import DataDriftPreset
report = Report(metrics=[DataDriftPreset()])
report.run(reference_data=train_df, current_data=prod_df)
report.show(mode='inline')
数据血缘(Data Lineage)追踪
数据血缘追踪数据从源头到消费的完整旅程。常用工具包括 Apache Atlas、OpenLineage、Marquez。
云数据平台
AWS 数据栈
- Amazon S3:对象存储,是数据湖的基础
- AWS Glue:无服务器 ETL 服务、数据目录
- Amazon Athena:用 SQL 分析 S3 数据
- Amazon Redshift:云数据仓库
- Amazon EMR:托管 Hadoop/Spark 集群
GCP 数据栈
- Google BigQuery:内置 ML 能力的无服务器数据仓库
- Cloud Dataflow:基于 Apache Beam 的数据处理
- Cloud Pub/Sub:实时消息服务(Kafka 的替代方案)
- Vertex AI:统一 ML 平台
Azure 数据栈
- Azure Data Lake Storage (ADLS):分层命名空间存储
- Azure Synapse Analytics:集成分析服务
- Azure Event Hub:大规模事件流(与 Kafka 兼容)
- Azure Databricks:基于 Spark 的分析平台
Snowflake 数据平台
Snowflake 是一个多云数据平台,其特点是把存储与计算分离的架构:
- 虚拟仓库(Virtual Warehouse):可独立扩展的计算集群
- 数据共享:组织间的安全数据共享
- Snowpipe:自动化的持续数据摄取
- Cortex:内置 AI/ML 能力
测验
Q1. Lambda 架构与 Kappa 架构的核心区别是什么?
答案:Lambda 架构同时维护批处理层与速度层,而 Kappa 架构只使用流处理层来简化架构。
说明:Lambda 架构能同时提供准确性(批处理)与实时性(流处理),但要分别维护两个层,复杂度较高。随着 Kafka Streams、Apache Flink 等工具的发展,仅靠流处理也能提供足够的准确性,这使得 Kappa 架构成为了现实可行的选择。
Q2. Apache Spark 中 DataFrame 与 RDD 的主要区别是什么?
答案:DataFrame 表示带 schema 的结构化数据,并通过 Catalyst 优化器实现自动查询优化。RDD 是无类型的低层级 API,能提供更精细的控制,但优化需要用户自己完成。
说明:大多数情况下推荐使用 DataFrame 或 Dataset API。只有在需要自定义序列化或底层控制时才使用 RDD。Spark 3.0+ 还通过 Adaptive Query Execution(AQE)支持运行时优化。
Q3. Kafka 中 Consumer Group 的作用是什么?
答案:Consumer Group 是订阅同一个 Topic 的消费者集合,通过把分区分配给各个消费者来实现并行处理与负载均衡。
说明:同一个 Partition 只能被同一个 Consumer Group 内的一个消费者读取。即使把消费者数量增加到超过分区数,多出来的消费者也会处于空闲状态。不同的 Consumer Group 可以独立读取同一个 Topic,因此同一个事件流可以用于多种目的。
Q4. dbt 中 ref() 函数的作用是什么?
答案:ref() 函数用于引用其他 dbt 模型,能自动推断模型间的依赖关系,并决定正确的执行顺序。
说明:使用 ref() 后,dbt 会构建 DAG(依赖关系图),并根据环境(开发/生产)自动解析出正确的数据库 schema 与表名。这大幅提升了代码的复用性与可维护性。
Q5. 特征存储中在线存储与离线存储的区别是什么?
答案:离线存储保存用于模型训练的大规模历史数据(Delta Lake、Parquet),在线存储则以低延迟提供用于实时推理的最新特征(Redis、DynamoDB)。
说明:两种存储之所以要分开,是因为它们的需求不同。训练需要批量处理数十亿行数据的高吞吐量,而推理需要毫秒级的低延迟。Feast 这类特征存储还承担着在两种存储之间保证特征一致性的角色。