Apache Hudi Rollback实现分析

1. 介绍

在发现有些commit出错时,可使用Hudi提供的rollback回滚至指定的commit,这样可防止出现错误的结果,并且当一次commit失败时,也会进行rollback操作,保证一次commit的原子性。

2. 分析

rollback(回滚)的入口在 HoodieWriteClient#rollback ,其依赖 HoodieWriteClient#rollbackInternal 方法完成实际的回滚,其核心代码如下

首先过滤出commit/delta_commit中是否存在待回滚instant的时间,如果存在,则进行回滚,回滚的核心方法为 doRollbackAndGetStats ,该方法在前一篇讲解savepoint时已经分析过,该方法会调用 HoodieTable#rollback 完成实际回滚动作,下面着重分析 HoodieTable#rollback 方法,对于MOR和COW不同类型有不同实现,下面一一进行分析。

2.1 HoodieCopyOnWriteTable#rollback

对于COW类型而言, rollback 核心代码如下

可以看到,进行回滚总体分为四步:1. 对于处理completed状态的instant,首先会将其转变至inflight状态,而对于不处于requested状态的instant(compaction会存在requested状态);2. 生成回滚请求;3. 进行回滚;4. 删除instant。

2.1.1 转变instant状态

对于处于completed状态的instant,将其转变至 inflight 状态,其核心代码如下

对于状态转变体现在文件名后缀的变化,即会变为 .inflght 状态。

2.1.2 生成回滚请求

回滚请求由 generateRollbackRequests 方法生成,其核心代码如下

会根据不同的分区路径生成不同的RollbackRequest,该方法会生成会生成DELETE DATA AND LOG FILES类型,指定分区路径的RollbackRequest。

2.1.3 进行回滚

通过 RollbackExecutor#performRollback 进行回滚,其核心代码如下

对于DELETE DATA FILES_ONLY类型的rollback ,会调用 deleteCleanedFiles 来删除数据文件,其核心代码如下

首先会过滤指定分区下所有与rollback时间相等的parquet文件,然后逐一删除。

对于DELETE DATA AND LOG FILES类型的rollback ,会调用同名的 deleteCleanedFiles 来删除文件,其核心代码如下

首先会过滤指定分区下所有与rollback时间相等的parquet/log文件,然后逐一删除。

对于APPEND ROLLBACK BLOCK类型的rollback ,会生成日志文件控制块并写入指定的文件中,在读取时,将不会读取该控制块的前一个块。

2.1.4 删除instant

在完成回滚后,还需要调用 deleteInflightAndRequestedInstant 来删除instant,其核心代码如下

删除instant主要是删除处于inflight和requested状态的在元数据目录下的文件。

2.2 HoodieMergeOnReadTable#rollback

对于MOR而言, rollback 核心代码如下

可以看到其流程与COW相同,不再赘述。

3. 总结

对于rollback而言,其主要分为四步:转变instant状态;2. 生成回滚请求;3. 进行回滚;4. 删除instant。而回滚时会分为三种情况,对于 DELETE_DATA_FILES_ONLYDELETE_DATA_AND_LOG_FILES 类型的rollback,会直接删除对应commit的数据文件和日志文件,而对于 APPEND_ROLLBACK_BLOCK 类型,则会写入控制块至文件中,在读取时不读取其前一个块。