Delta

为什么需要 Delta Lake

https://github.com/delta-io/delta
虽然数据湖在数据范围方面迈出了一大步,但是也面临了很多问题,主要概括如下:

  • 数据湖的读写是不可靠的。数据工程师经常遇到不安全写入数据湖的问题,导致读者在写入期间看到垃圾数据。他们必须构建方法以确保读者在写入期间始终看到一致的数据。
  • 数据湖中的数据质量很低。将非结构化数据转储到数据湖中是非常容易的。但这是以数据质量为代价的。没有任何验证模式和数据的机制,导致数据湖的数据质量很差。因此,努力挖掘这些数据的分析项目也会失败。
  • 随着数据的增加,处理性能很差。随着数据湖中存储的数据量增加,文件和目录的数量也会增加。处理数据的作业和查询引擎在处理元数据操作上花费大量时间。在有流作业的情况下,这个问题更加明显。
  • 数据湖中数据的更新非常困难。工程师需要构建复杂的管道来读取整个分区或表,修改数据并将其写回。这种模式效率低,并且难以维护。

Delta特性

Delta_第1张图片
Delta

Delta Lake 提供以下主要功能:

支持 ACID 事务

Delta Lake 在多并发写入之间提供 ACID 事务保证。每次写入都是一个事务,并且在事务日志中记录了写入的序列顺序。事务日志跟踪文件级别的写入并使用乐观并发控制,这非常适合数据湖,因为多次写入/修改相同的文件很少发生。在存在冲突的情况下,Delta Lake 会抛出并发修改异常以便用户能够处理它们并重试其作业。Delta Lake 还提供强大的可序列化隔离级别,允许工程师持续写入目录或表,并允许消费者继续从同一目录或表中读取。读者将看到阅读开始时存在的最新快照。

乐观并发控制(又名“乐观锁”,Optimistic Concurrency Control,缩写“OCC”)是一种并发控制的方法。它假设多用户并发的事务在处理时不会彼此互相影响,各事务能够在不产生锁的情况下处理各自影响的那部分数据。在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,正在提交的事务会进行回滚。
乐观并发控制的事务包括以下阶段:[来源请求]
乐观并发控制的事务包括以下阶段:[来源请求]

  • 读取:事务将数据读入缓存,这时系统会给事务分派一个时间戳。
  • 校验:事务执行完毕后,进行提交。这时同步校验所有事务,如果事务所读取的数据在读取之后又被其他事务修改,则产生冲突,事务被中断回滚。
  • 写入:通过校验阶段后,将更新的数据写入数据库。
模式管理(Schema management)

Delta Lake 自动验证正在被写的 DataFrame 模式是否与表的模式兼容。表中存在但不在 DataFrame 中的列设置为 null。如果 DataFrame 有表中不存在的列,则此操作会引发异常。Delta Lake 具有显式添加新列的 DDL 以及自动更新模式的能力。

可扩展元数据处理

Delta Lake 将表或目录的元数据信息存储在事务日志中,而不是 Metastore 中。这允许 Delta Lake 在恒定时间内列出大型目录中的文件,同时在读取数据时非常高效。

数据版本

Delta Lake 允许用户读取表或目录之前的快照。当文件被修改文件时,Delta Lake 会创建较新版本的文件并保留旧版本的文件。当用户想要读取旧版本的表或目录时,他们可以在 Ap>ache Spark 的读取 API 中提供时间戳或版本号,Delta Lake 根据事务日志中的信息构建该时间戳或版本的完整快照。这允许用户重现之前的数据,并在需要时将表还原为旧版本的数据。

统一流和批处理 Sink

除批量写入外,Delta Lake 还可用作 Apache Spark structured streaming 的高效流式 sink。结合 ACID 事务和可扩展的元数据处理,高效的流式 sink 现在可以实现大量近实时分析用例,而无需同时维护复杂的流式传输和批处理管道。

数据存储格式采用开源的

Delta Lake 中的所有数据都是使用 Apache Parquet 格式存储,使 Delta Lake 能够利用 Parquet 原生的高效压缩和编码方案。

记录更新和删除

这个功能马上可以使用。Delta Lake 将支持 merge, update 和 delete 等 DML 命令。这使得数据工程师可以轻松地在数据湖中插入/更新和删除记录。 由于 Delta Lake 以文件级粒度跟踪和修改数据,因此它比读取和覆盖整个分区或表更有效。

数据异常处理

Delta Lake 还将支持新的 API 来设置表或目录的数据异常。工程师能够设置一个布尔条件并调整报警阈值以处理数据异常。当 Apache Spark 作业写入表或目录时,Delta Lake 将自动验证记录,当数据存在异常时,它将根据提供的设置来处理记录。

100% 兼容 Apache Spark API

这点非常重要。开发人员可以将 Delta Lake 与他们现有的数据管道一起使用,仅需要做一些细微的修改。比如我们之前将处理结果保存成 Parquet 文件,如果想使用 Delta Lake 仅仅需要做如下修改:

dataframe
   .write
   .format("parquet")
   .save("/data")
 
修改成
 
dataframe
   .write
   .format("delta")
   .save("/data")

测试类

import org.apache.spark.sql.SparkSession

object DeltaTest {

    def main(args: Array[String]): Unit = {

        val spark  = SparkSession.builder().appName("Simple Application").master("local").getOrCreate()

        val data = spark.range(0, 5)

        //create table
        data.write.format("delta").save("/tmp/delta-table")

        val data1 = spark.range(5, 10)

        //update the table
        data1.write.format("delta").mode("overwrite").save("/tmp/delta-table")

      //read data
        val df = spark.read.format("delta").load("/tmp/delta-table")
        df.show()
        //可以指定 versionAsOf 参数用来访问数据表的一个 snapshot。
        //使用 Time Travel 功能读取Delta中老版本的数据
        val df1 = spark.read.format("delta").option("versionAsOf", 0).load("/tmp/delta-table")
        df1.show()

        //Structured Streaming 读写Delta
        val streamingDf = spark.readStream.format("rate").load()
        //val stream = streamingDf.select($"value" as "id").writeStream.format("delta").option("checkpointLocation", "/tmp/checkpoint").start("/tmp/delta-table")

        //对 Delta 进行流式读取
        val stream2 = spark.readStream.format("delta").load("/tmp/delta-table").writeStream.format("console").start()
    }
}
Delta_第2张图片
parquet

_delta_log的中XXX.josn文件代表了对文件修改记录信息。


Delta_第3张图片
_delta_log
Delta_第4张图片
json文件

参考:
https://www.iteblog.com/archives/2545.html?hmsr=w3cschool.cn
https://docs.delta.io/latest/delta-batch.html

你可能感兴趣的:(Delta)