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_ONLY
和 DELETE_DATA_AND_LOG_FILES
类型的rollback,会直接删除对应commit的数据文件和日志文件,而对于 APPEND_ROLLBACK_BLOCK
类型,则会写入控制块至文件中,在读取时不读取其前一个块。