【架构实战】数据湖架构设计与实践

一、为什么需要数据湖

传统数据仓库的局限性:

  • 结构化数据为主,难以处理非结构化数据
  • Schema固定,难以适应业务变化
  • 数据预处理后丢失细节
  • 存储成本高

数据湖的特点:

  • 存储各种类型数据(结构化、半结构化、非结构化)
  • Schema-on-Read(读时模式)
  • 保留原始数据,可重复计算
  • 降低数据存储成本

二、数据湖架构

1. 核心组件

复制代码
数据源
├── 日志系统(Kafka)
├── 业务数据库(MySQL/PostgreSQL)
├── 埋点数据(App/Web)
├── 外部API
└── 文件上传(S3/HDFS)
        ↓
数据采集层
├── Flume(日志)
├── Debezium(CDC)
├── Sqoop(批量)
└── Kafka Connect
        ↓
数据存储层
├── 对象存储(MinIO/S3/HDFS)
├── Delta Lake/Iceberg/Hudi
└── 数据目录(Apache Atlas)
        ↓
数据处理层
├── Spark
├── Flink
└── Presto/Trino
        ↓
数据应用层
├── BI报表
├── 数据科学
└── ML平台

2. 技术选型对比

组件 选项 推荐
存储 HDFS/S3/MinIO S3(云)/MinIO(私有)
格式 Parquet/ORC/Avro Parquet
表格式 Delta/Iceberg/Hudi Delta Lake
查询引擎 Presto/Trino/Spark Trino
元数据 Hive Metastore/Glue Hive Metastore

三、Delta Lake实战

1. Delta Lake简介

Delta Lake是Databricks开源的存储层,提供:

  • ACID事务
  • 可扩展元数据处理
  • 时间旅行(Time Travel)
  • 模式强制和演化
  • 流批一体

2. Spark + Delta Lake

依赖配置:

xml 复制代码
<dependency>
    <groupId>io.delta</groupId>
    <artifactId>delta-core_2.12</artifactId>
    <version>2.4.0</version>
</dependency>

写入数据:

python 复制代码
from delta.tables import DeltaTable
from pyspark.sql import SparkSession

spark = SparkSession.builder \
    .appName("DataLakeDemo") \
    .config("spark.sql.extensions", "io.delta.sql.DeltaSparkSessionExtension") \
    .config("spark.sql.catalog.spark_catalog", "org.apache.spark.sql.delta.catalog.DeltaCatalog") \
    .getOrCreate()

# 批量写入
df = spark.read.format("json").load("/data/events/*.json")

df.write \
    .format("delta") \
    .mode("overwrite") \
    .partitionBy("date", "event_type") \
    .option("mergeSchema", "true") \
    .save("/delta/events")

流式写入:

python 复制代码
# Kafka -> Delta Lake
streaming_df = spark.readStream \
    .format("kafka") \
    .option("kafka.bootstrap.servers", "localhost:9092") \
    .option("subscribe", "events") \
    .load()

query = streaming_df.selectExpr("CAST(key AS STRING)", "CAST(value AS STRING)") \
    .writeStream \
    .format("delta") \
    .option("checkpointLocation", "/delta/events/_checkpoints") \
    .outputMode("append") \
    .start("/delta/events")

读取数据:

python 复制代码
# 读取最新数据
df = spark.read.format("delta").load("/delta/events")

# 时间旅行 - 读取历史版本
df_v1 = spark.read \
    .format("delta") \
    .option("versionAsOf", 1) \
    .load("/delta/events")

# 时间旅行 - 读取指定时间点
df_before = spark.read \
    .format("delta") \
    .option("timestampAsOf", "2024-01-01T00:00:00") \
    .load("/delta/events")

增量读取:

python 复制代码
# 获取增量数据
deltaTable = DeltaTable.forPath(spark, "/delta/events")

# 只读取新数据
newDF = deltaTable.toDF().filter(col("date") >= "2024-01-15")

3. UPSERT操作

python 复制代码
from delta.tables import DeltaTable

# Merge操作(UPSERT)
deltaTable = DeltaTable.forPath(spark, "/delta/users")

deltaTable.alias("old").merge(
    updatesDF.alias("new"),
    "old.user_id = new.user_id"
).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute()

4. 数据优化

python 复制代码
# VACUUM - 删除不需要的文件(保留7天)
deltaTable.vacuum(retentionHours = 168)

# OPTIMIZE - 优化小文件
deltaTable.optimize().where("date = '2024-01-15'").zOrderBy("user_id").execute()

四、Hudi实战

1. Hudi简介

Hudi(Hadoop Upsert Delete and Incremental)特点:

  • 支持UPSERT/DELETE
  • 增量拉取
  • 多种表类型(Copy on Write / Merge on Read)

2. Spark + Hudi

python 复制代码
from pyspark.sql import SparkSession

spark = SparkSession.builder \
    .appName("HudiDemo") \
    .config("spark.serializer", "org.apache.spark.serializer.KryoSerializer") \
    .config("spark.sql.extensions", "org.apache.spark.sql.hudi.HoodieSparkSessionExtension") \
    .getOrCreate()

# 写入数据
hoodie_options = {
    'hoodie.table.name': 'events',
    'hoodie.datasource.write.recordkey.field': 'id',
    'hoodie.datasource.write.partitionpath.field': 'date',
    'hoodie.datasource.write.table.type': 'COPY_ON_WRITE',
    'hoodie.datasource.write.operation': 'bulk_insert',
    'hoodie.datasource.write.precombine.field': 'ts',
    'hoodie.upsert.shuffle.parallelism': '200',
    'hoodie.insert.shuffle.parallelism': '200'
}

df.write \
    .format("hudi") \
    .options(**hoodie_options) \
    .mode("append") \
    .save("hdfs://namenode:8020/hudi/events")

3. 增量拉取

python 复制代码
# 增量拉取
spark.read \
    .format("hudi") \
    .load("hdfs://namenode:8020/hudi/events") \
    .createOrReplaceTempView("hudi_events_snapshot")

# 获取指定时间点后的数据
incremental_df = spark.sql("""
    SELECT * FROM hudi_events_snapshot 
    WHERE hoodie_commit_time > '20240115120000'
""")

五、数据湖最佳实践

1. 表设计

sql 复制代码
-- 使用分区表
CREATE TABLE events (
    id BIGINT,
    user_id BIGINT,
    event_type STRING,
    properties STRING,
    event_time TIMESTAMP
)
USING delta
PARTITIONED BY (date STRING, event_type STRING)
LOCATION '/delta/events'

-- 配置Z-Order优化
OPTIMIZE events
WHERE date = '2024-01-15'
ZORDER BY (user_id, event_time)

2. 数据治理

python 复制代码
# 数据质量检查
from great_expectations import GreatExpectations

context = GreatExpectations()
checkpoint = context.get_checkpoint("events_quality")

results = checkpoint.run(
    batch_request={
        "datasource_name": "my_datasource",
        "data_asset_name": "events",
    }
)

if not results["success"]:
    # 发送告警
    send_alert(results["failed_expectations"])

3. 权限控制

sql 复制代码
-- 基于列的权限控制
GRANT SELECT(event_time, event_type) ON events TO analyst_role;
GRANT SELECT ON events TO data_scientist_role;

-- 基于行的权限控制
CREATE TABLE events_filtered AS
SELECT * FROM events
WHERE CASE 
    WHEN current_user() = 'admin' THEN true
    ELSE date >= '2024-01-01'
END

六、总结

数据湖是现代数据平台的核心:

  • Lakehouse:结合数据湖和数据仓库优点
  • Delta Lake:成熟的表格式,支持ACID
  • Hudi:适合CDC场景,支持增量处理
  • 最佳实践:分区、Z-Order、数据质量

实施建议:

  1. 评估数据量和业务需求
  2. 选择合适的表格式
  3. 设计合理的分区策略
  4. 建立数据质量监控

个人观点,仅供参考

相关推荐
清水白石0085 小时前
Python 编程实战全景:从基础语法到插件架构、异步性能与工程最佳实践
开发语言·python·架构
ting94520006 小时前
HunyuanOCR 全方位深度解析
人工智能·架构
heimeiyingwang8 小时前
【架构实战】CQRS架构模式实战
架构
技术传感器8 小时前
Hermes为什么开始像基础设施:11万星、RCE修复与生态接入
人工智能·安全·架构·aigc
执于代码9 小时前
智能客服的agent 的架构和作用以及源码分析
架构
AI创界者10 小时前
【独家解析】Ernie-Image-AIO-Rapid一键部署本地运行整合包:深度融合架构如何重塑AI绘图效率?4K超分与硬件适配全指南
人工智能·架构
BullSmall11 小时前
Redis 双机部署 完整方案(两种架构,适配两台机器)
java·redis·架构
SamDeepThinking14 小时前
适合中小型企业的出口入口网关微服务
java·后端·架构
LSL666_14 小时前
微服务架构
微服务·云原生·架构
威迪斯特14 小时前
GoFr框架:加速微服务开发的Go语言利器
开发语言·后端·微服务·架构·golang·命令行框架·gofr框架