Hudi剖析|详解ApacheHudi如何节约宝贵的存储空间

1. 介绍

对于旧版本的数据 Hudi 需要将其删除以节约宝贵的存储空间, Clean 操作有两种策略: KEEP_LATEST_FILE_VERSIONS (保留最新的文件版本)和 KEEP_LATEST_COMMITS (保留最新的提交),不同的策略会有不同的行为, Clean 阶段被分为生成 HoodieCleanerPlan 和执行 HoodieCleanerPlan ,下面分析 Clean 的具体实现。

2. 分析

在每次 commit 时,会判断是否开启自动 clean 来执行 clean 操作,或者由用户手动触发 clean 操作。

2.1 生成HoodieCleanerPlan

对于在 commit 时执行的 clean 操作,其核心入口为 HoodieCleanClient#clean ,核心代码如下

需要先处理未完成的 clean ,然后再通过 scheduleClean 方法生成 HoodieCleanerPlan ,其核心代码如下

会继续调用 HoodieCopyOnWriteTable#scheduleClean 生成 HoodieCleanerPlan ,核心代码如下

对于 HoodieCleanerPlan 的生成,首先会找出最早需要保留的 instant ,然后获取对应所有的分区路径。

2.1.1 获取待Clean的所有分区

获取所有待clean分区路径的核心代码如下

可以看到,如果开启了增量 clean 并且当前 instant 不为空,同时策略为 KEEP_LATEST_COMMITS 时,则会先取上次已完成的 clean ,然后过滤出从上次已完成 cleaninstant 时间到当前clean中需要保留的最早的 instant 时间,并获取对应的分区路径;否则直接返回所有的分区路径。

在获取了所有待 clean 的分区路径后,还需要调用 HoodieCleanHelper#getDeletePaths 获取所有待删除的文件路径。

2.1.2 获取待删除文件

获取待删除文件的核心代码如下

可以看到,根据策略的不同调用不同方法来获取分区下待删除的所有文件。

对于 KEEP_LATEST_COMMITS 策略而言, getFilesToCleanKeepingLatestCommits 核心代码如下

可以看到,找出待删除的文件需要会经过一系列判断,如不能删除 savepoint 文件,不能删除小于最早需要保留的 instant 的时间文件(因为该文件可能还是会被使用),不能删除待压缩的文件。仅删除那些小于最早需要保留的 instant 的文件,并且如果是 MOR 类型,那么可以将日志文件一并删除。

对于 KEEP_LATEST_FILE_VERSIONS 策略而言, getFilesToCleanKeepingLatestVersions 获取待删除文件的核心代码如下

可以看到,对于 savepoint 的文件也不能删除,也不能删除待压缩的文件。仅删除那些不需要继续保留的版本的文件,如果是 MOR 类型,那么可以将日志文件一并删除。

2.2 执行HoodieCleanerPlan

在生成 HoodieCleanerPlan 后,会将其序列化并保存至元数据目录,然后开始执行,其核心在 HoodieCleanClient#runClean ,其核心代码如下

这块代码的核心逻辑非常简单,首先反序列出 HoodieCleanerPlan ,然后再开始执行删除操作,实际删除文件操作由 deleteFilesFunc 处理,然后返回 Clean 的统计信息。

3. 总结

对于 Clean 操作, Hudi 提供了两种策略:基于文件版本和基于提交保留数。并且将 Clean 分为生成 HoodieCleanerPlan 和执行 HoodieCleanerPlan 两个阶段,两阶段并不直接关联.在生成 HoodieCleanerPlan 时会找出所有符合指定策略的待删除文件,并且为了避免每次全分区处理,Hudi还提供了增量 Clean 配置项,即仅仅只处理从上次 Clean 后影响的分区,然后将 HoodieCleanerPlan 序列化至元数据(.aux)目录,在执行阶段会从元数据目录中反序列化后执行删除文件操作。