数据湖三剑客:Delta Lake,Hudi与Iceberg详解|青训营笔记

206 阅读6分钟

这是我参与「第四届青训营 」笔记创作活动的的第11天

  • 发展历史
    • 数据湖发展阶段
      • Hadoop
        • 分布式存储HDFS
          • 使用目录来区分不同的数据集
          • 好处
            • 同一公司/组织可以使用共享存储
            • 数据访问方便,灵活性高
          • 坏处
            • 没有记录文件的schema(包括列名、列类型),经常使用schema On Query的方式
            • 难以得知数据集包含了哪些文件,是通过什么样的分区组织的
            • 如果多个程序都在修改这个数据集(修改数据、修改表结构),其他程序难以配合做修改
        • Hive Metastore
          • 对数据湖中的数据集进行集中"定义"
            • 数据湖中存在了哪些数据集
            • 它们都存储在什么目录
            • 数据集的schema是什么样子的
            • 数据集有哪些分区,每个分区的目录是什么
        • 湖仓一体
          • 数据仓库
            • 数据仓库将数据从数据源提取和转换,加载到目的地
            • 数据仓库存储+计算不分离
            • 数据仓库严格控制写入数据的schema
          • 湖仓一体(数据湖的现状)
            • 结合了数据湖和数据仓库的优势
            • 将数据仓库中对于数据的严格管理直接实现到了低成本的分布式存储之上
            • Key Features
              • Transaction ACID
              • Schema管理
              • 存储计算分离
              • 支持多种计算引擎和文件格式
  • 核心技术
    • Time Travel
      • 要点
          1. 每次写入都生成一个新的元数据文件,记录变更
          1. 分区数据在update时,不要删除旧数据,保证新旧共存
          1. 元数据中存储具体的文件路径,而不仅仅是分区文件夹
      • 实现
          1. 每一次写入操作,创建一个新的json文件,以递增版本号命名,记录本次新增/删除的文件
          1. 每当产生Njson,做一次聚合,记录完整的分区文件信息
          1. checkpoint记录上次做聚合的版本号
    • Transaction
      • 数据湖中的ACID
        • Atomicity
          • 本次写入要么对用户可见,要么不可见(需要设计)
            • 写入流程
              • 先写数据文件,再写元数据文件
            • 从用户可见性入手
                1. 用户只会读取以版本号数据命名的json文件,每次都读取到最大的版本号作为数据集的现状。
                1. 新的写入写完parquet后开始写json文件,使用hash值对json文件命名
                1. 直到json文件内容写入完毕,利用hdfsrenameIfAbsent能力将hash值文件名替换为数字文件名,到此为止,commmit完成,新的读取将以数字文件名作为最新版本。
            • 读写冲突已经解决
                1. 新的写入除非commit,否则用户读不到
                1. 用户正在读的分区,被另一个写入进行了更新,数据不会进行替换,而是共存
        • Consistency
          • 输入是什么,落盘就是什么(由计算引擎保证)
        • Isolation
          • 正确解决读写冲突和写写冲突(需要设计)
          • update写入流程
              1. 从最新的版本中,获取需要update的分区
              1. 乐观锁先把该写入的文件全落盘,然后进入写json阶段
              1. 分情况
                1. 发现版本号和一开始没区别,直接写新的版本
                1. 发现版本号增加了,看看新增的这些版本有没有更新我要更新的分区
                  1. 没有,直接写新版本
                  1. 有,两者都更新了同一分区,重新update
        • Durability
          • 落完数据后,即便服务器重启结果不变(由存储引擎保证)
    • Schema Evolution
      • Add/Drop/Rename
        • 重要
          • 用户并不直接读取parquet文件本身,而是通过数据湖接口读取,如Dataset<Row> ds = simpleDataLake.read(mytable).option(date=2020-01-01)
          • 数据湖内部会读取应该读的parquet,并在schema上做进一步处理
        • IDdatametadata的列名做一一对应
            1. 唯一确定的ID。新增列赋予新ID。删列ID不复用。
            1. 写入数据后,ID也写入数据文件
            1. 读取数据时,用ID做映射,如果
              1. data中没有,metadata中有:Add
              1. data中有,metadata中没有:Drop
              1. datametadata中都有同一ID,但是name不同:RENAME
  • 各有所长
    • Iceberg
      • 工作重点
        • 用户体验
          • Schema Evolution
          • Partition Evolution
          • Hidden Partition
          • Time Travel
          • Version Rollback
        • 性能
          • 快速file plan
          • 更多的filter方式
        • 可靠性
          • ACID Transaction
        • 完全开源,由Apache孵化开发
      • Well-designed Metadata Layer
        • Metadata files定义了表结构,存储了snapshot信息,分区列信息等
        • Manifest lists存储了一个snapshot中所有manifest的信息
        • manifests存储了一些data files的信息
        • data files就是具体的数据文件
      • Data File Filter
        • 一些有助于filter的数据被层层记录,比如
            1. Metadata file记录了每个data file的分区范围
            1. Manifest list记录了每个Metadata file的分区范围,分区可以被快速定位,可以做Manifest list级别裁剪
            1. Metadata file记录了每个data file每一列的最大值,最小值可以通过其他的列(UserId)做data file级别裁剪
      • Hidden Partition
        • 传统的分区方式
          • 数据中包含了date列,则按照date分区;如果希望按照hour分区,则需要新增hour
        • Iceberg的分区方式
          • 数据中包含timestamp列,设置好partition transform方式
            • 设置为date时,iceberg帮你转化为date分区
            • 设置为hour时,iceberg帮你转化为hour分区
            • iceberg记录了这层转化关系,并且按照你的需求进行Partition Evolution
    • Hudi
      • 工作重点
        • Timeline service
          • Hudi管理transaction的方式
          • 记录的信息类似于metadata
        • Hudi Table Type
          • Copy on write/Merge on Read
        • 高效的Upserts
          • update or insert
          • 每条样本都有一个主键PK,当Upsert一条数据时,如果现有的数据中有这个PK,则update这条数据。否则直接insert这条数据。
        • 索引表
          • 快速定位一条数据的位置
        • Incremental
          • 某个时间点后新增的数据
        • Streaming Ingestion Service
        • 完全开源,由Apache孵化
    • Delta Lake
      • 工作重点
        • ACID Transaction
        • Schema校验
        • 流批一体
        • Time Travel
        • update/delete
        • Z-order优化
        • 只开源了一部分,由Databricks自己主导开发,Z-order等优化的实现未开源
  • 总结场景
    • 技术选型
      • 短期来看,每个项目都有一些属于自己的功能
        • 如果强需求Upserts,也许Hudi是最好的选择
        • 如果希望可扩展性强,那么设计优良的Iceberg是最好的选择
        • 如果希望用上Z-order优化,Delta Lake是最好的选择
      • 长期来看,数据湖取代Hive,成为HDFS上的表格式标准是必然的,在选择之前问自己四个问题
        • 我需要的feature在哪个数据湖上最稳定
        • 哪一个数据湖能够用最简单的加入方式(SQL),用上最完善的功能
        • 哪一个数据湖有计算引擎侧的支持和社区的支持
        • 哪一个数据湖的版本管理做的最好,最鲁棒
    • 总结
      • 数据湖的最新发展状态是湖仓一体
      • 数据湖以低存储成本提供了ACID TransactionSchema EvolutionTime Travel等高级功能