1. 默认清理策略
在hudi系列-旧文件清理(clean)中介绍了清理的大致流程,可以防止文件系统的无限膨胀,所以它是必须的。hudi提供三种查询方式:读优化、快照读、增量读,无论是哪种方式,由于hudi的文件组织是有版本的概念(FileGroup,FileSlice),旧版本的文件持续在执行清理,如果被清理的文件正在读取或者即将被读取到,那岂不是很影响使用,所以我们需要设置合理的清理策略保障上层数据处理任务的平稳运行,提高系统的容错性。
- KEEP_LATEST_COMMITS:默认策略,表示保留最后n次提交,默认为10 ,通过参数hoodie.cleaner.commits.retained或clean.retain_commits(flink)设置;
- KEEP_LATES_FILE_VERSIONS:保留最后n个文件版本,默认为3,通过参数hoodie.cleaner.fileversions.retained设置;
- KEEP_LATEST_BY_HOURS:保留最后n小时,默认24小时,通过参数hoodie.cleaner.hours.retained设置,这是0.11版本后新增的;
可以通过hoodie.cleaner.policy
来配置使用以上哪一种清理策略。
2. 选择清理策略
在flink+hudi的使用场景中,一般来说当checkpoint时触发一次hudi的commit(如果数据量过大,在两次checkpoint之间也会自动触发 ),所以第一种策略逻辑上与第三种一致,如果checkpoint时间为1分钟,那么设置保留最后60次提交,即表示保留最后1小时。从这种角度可以将三种策略分为两类:
- 基于时间的策略:保留最后N次提交、保留最后N小时提交,支持增量清理和全量清理
- 基于版本的策略:保留最后N个版本,只支持全量清理
2.2 选择基于时间的策略
一般使用基于时间的策略居多,可以通过hoodie.cleaner.incremental.mode开启增量清理来优化性能,增量清理需要依赖.hoodie下的元数据文件来确定增量范围内做了多少commit,以及每次commit涉及的表分区,这样就避免了每次都全量扫描整表
- 通过策略具体的参数值N计算本次清理需要保留的最早时刻earliestInstant(
CleanPlanner#getEarliestCommitToRetain
),在该节点之前的都在清理范围 -
如果开启了增量清理,获取上一次清理任务的元数据文件(包含了上次的时间节点lastEarliestInstant),从而确定本次需要增量清理的时间范围
2.1. 从timeline中找到所有在增量时间范围[lastEarliestInstant,earliestInstant]内的completed commit
2.2. 解析每个commit元数据文件,得到涉及到的写分区
- 如果开启了增量清理且是首次清理,或是全量清理,则表示整个表所有分区都有可能发生了写
- 从每个分区下的所有文件组、文件分片中得到满足清理条件的数据文件(base+log),
CleanPlanner#getFilesToCleanKeepingLatestCommits
- 生成清理计划,后续根据计划执行文件删除
2.2 推荐KEEP_LATEST_COMMITS策略
对于使用来说,保留N小时这种策略更为直观,而不是保留N次提交再计算出时间,那为什么推荐使用KEEP_LATEST_COMMITS?
主要是因为KEEP_LATEST_BY_HOURS在使用增量清理时可能会出现异常情况,从上面知道,增量清理是要依赖.hoodie下的元数据,经过文件归档后,整个timeline可能就不能覆盖每次清理的增量时间范围,这会造成漏清理甚至永远不会发生清理。
我们可以通过调整hoodie.keep.max.commits和hoodie.keep.min.commits使得归档后还能保留更久的元数据,但是该值不好确定,而且在修改保留N小时也要同步更改这两个值。
当我们选择KEEP_LATEST_COMMITS策略时,只要hoodie.cleaner.commits.retained < hoodie.keep.min.commits即可,这样就可以保证元数据timeline能一直覆盖每次增量清理范围。
如果使用的是flink往hudi写数据,则只要设置clean.retain_commits单个配置即可,HoodieTableFactory#setupCompactionOptions
hoodie.cleaner.commits.retained=clean.retain_commits
hoodie.keep.min.commits=archive.min_commits=clean.retain_commits+10
hoodie.keep.max.commits=archive.max_commits=clean.retain_commits+20
3. 设置策略值
clean.retain_commits默认是10,如何设置一个合适的值,可以从几方面考虑
- 虽然理论可以设置到Integer.MAX_VALUE,过大的值会导致表数据目录下过多小文件,很多操作都需要进行listing file操作,会造成很大压力,甚至OOM
- 如果基于hudi使用cdc,则需要考虑上层的应用要求保留多久的增量数据
- 数据保留的时长需要比最大查询耗时要长