Delta Lake源码分析

本文深入分析Delta Lake的源码,涵盖了Delta Lake的元数据结构,包括Protocol、Metadata等。详细阐述了snapshot的生成过程,特别是如何在有或无checkpoint文件的情况下计算快照。此外,还探讨了日志提交的步骤,冲突检测的并发控制策略,以及delete、update和merge操作的实现细节。
摘要由CSDN通过智能技术生成

Delta Lake源码分析

Delta Lake元数据

delta lake 包含Protocol、Metadata、FileAction(AddFile、RemoveFile)、CommitInfo和SetTransaction这几种元数据action。

  1. Protocol:这是delta lake自身的版本管理,一般只出现在第一次的commit日志里(之后版本升级应该也会有);
  2. Metadata:存储delta表的schema信息,第一次commit和每次修改schema时出现,以最后一次出现的为准;
  3. FileAction:文件的相关操作,delta lake的文件操作只有添加文件和删除文件;
  4. CommitInfo:保存关于本次更改的原始信息,如修改时间,操作类型,读取的数据版本等;
  5. SetTransaction:设置application的提交版本,一般用于流式计算的一致性控制(exactlyOnce)。
//初始的commit log会包含protocol和metaData的信息
{"commitInfo":{"timestamp":1576480709055,"operation":"WRITE","operationParameters":{"mode":"ErrorIfExists","partitionBy":"[]"},"isBlindAppend":true}}
{"protocol":{"minReaderVersion":1,"minWriterVersion":2}}
{"metaData":{"id":"fe0948b9-8253-4942-9e28-3a89321a004d","format":{"provider":"parquet","options":{}},"schemaString":"{\"type\":\"struct\",\"fields\":[{\"name\":\"azkaban_tag\",\"type\":\"string\",\"nullable\":true,\"metadata\":{}},{\"name\":\"project_name\",\"type\":\"string\",\"nullable\":true,\"metadata\":{}},{\"name\":\"flow_name\",\"type\":\"string\",\"nullable\":true,\"metadata\":{}},{\"name\":\"job_name\",\"type\":\"string\",\"nullable\":true,\"metadata\":{}},{\"name\":\"application_name\",\"type\":\"string\",\"nullable\":true,\"metadata\":{}},{\"name\":\"queue_name\",\"type\":\"string\",\"nullable\":true,\"metadata\":{}},{\"name\":\"master_name\",\"type\":\"string\",\"nullable\":true,\"metadata\":{}}]}","partitionColumns":[],"configuration":{},"createdTime":1576480707164}}
{"add":{"path":"part-00000-dc1d1431-1e4b-4337-b111-6a447bad15fc-c000.snappy.parquet","partitionValues":{},"size":1443338,"modificationTime":1576480711000,"dataChange":true}}

//之后的commit log会记录下当前操作的信息
{"commitInfo":{"timestamp":1576481270646,"operation":"DELETE","operationParameters":{"predicate":"[\"(`master_name` = 'mob_analyse')\"]"},"readVersion":0,"isBlindAppend":false}}
{"remove":{"path":"part-00000-dc1d1431-1e4b-4337-b111-6a447bad15fc-c000.snappy.parquet","deletionTimestamp":1576481270643,"dataChange":true}}
{"add":{"path":"part-00000-d6431884-390d-4837-865c-f6e52f0e2cf5-c000.snappy.parquet","partitionValues":{},"size":1430267,"modificationTime":1576481273000,"dataChange":true}}

delta lake元数据管理

snapshot生成

当存在checkpoint文件时,DeltaLog类的currentSnapshot会根据checkpoint和之后的json日志来计算快照。

  1. 通过loadMetadataFromFile()方法读取_last_checkpoint文件获得最新的checkpoint路径;
  2. 通过LogStore.listFrom()方法获得checkpoint之后版本的delta log文件;
  3. 使用verifyDeltaVersions方法验证delta log的文件是否是连续的(日志版本必须是连续的,每个commit log都需要被计算);
  4. 解析并聚合checkpoint和delta log为Seq[DeltaLogFileIndex],然后new Snapshot();
  5. Snapshot里的stateReconstruction会使用InMemoryLogReplay来计算日志中的各种action,获得最终的状态信息。

当没有checkpoint文件时,通过DeltaLog类的update方法来计算快照。

  1. 当不存在_last_checkpoint文件时,new一个版本号为-1的Snapshot;
  2. 检测到currentSnapshot的版本为-1,调用update方法,实际工作的是updateInternal方法,它会把当前的快照更新到最新版本;
  3. updateInternal会遍历出版本号小于等于 max(当前版本,0)的checkpoint文件和delta log,并通过new Snapshot将这些更新添加到当前快照中。
@volatile private var currentSnapshot: Snapshot = lastCheckpoint.map { c =>
    val checkpointFiles = c.parts
      .map(p => checkpointFileWithParts(logPath, c.version, p))     //目前版本没用到parts,疑似商业版功能
      .getOrElse(Seq(checkpointFileSingular(logPath, c.version)))   //返回最新checkpoint文件路径
    val deltas = store.listFrom(deltaFile(logPath, c.version + 1))  //返回checkpoint之后版本的json文件
      .filter(f => isDeltaFile(f.getPath))
      .toArray
    val deltaVersions = deltas.map(f => deltaVersion(f.getPath))
    verifyDeltaVersions(deltaVersions)  //验证版本日志是否连续
    val newVersion = delt
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值