本文要讨论的是这样一个问题:使用Hudi的COW表时,有一个很明显的现象:当表中有大量的更新数据写入时,落地的parquet文件往往总大小往往要double,每写入一次就会double一次,对于数据体量非常大,且每次都有大量更新的数据来说,不禁会让人担心:这种数据膨胀是否会快速耗尽存储资源?有没有可以克制的方法?其实,这并不是一个问题,而是Hudi表的正常表现,我们先从原理上来看一下产生这个问题背后的原因。

对于Huidi COW表的工作方式,下图有非常清晰的演示:

在这里插入图片描述

我们要注意到:Copy-On-Write中的"Copy"是拷贝的什么呢?从图中不难看出是“文件中那些没有变化的数据”,Hudi将这些数据copy出来,再append上新增或更新的后数据重新落地为一个新的文件!这样我们就不难理解为什么COW下会产生这么多的文件了。

设想一下:假如一个COW表在初始写入时生成了10个文件,现在正有一个新的写操作,假设写入的数据都是更新现有的数据,且这些数据又刚好分布于10个文件内(这种情形可能性很大),那这次写入之后,文件数量将会变成20个,数据总量也差不多正好的是double,原因正是Copy-On-Write的工作机制导致的。当然,如果这时我们去查这张表,数据条数并不会double,但是如果使用time travel方式查询,大多数数据其实是有两个commit版本的。

那如果真如前面所假设的情况:这张表的数据体量非常大,且每次都有大量的更新数据,开发人员势必要担心数据膨胀的问题,所以我们需要Hudi能控制其保留的commit数量,也就是限制保存数据变更的版本数。

而Hudi控制这一点的配置项正是hoodie.cleaner.commits.retained,配置项常量名是HoodieCompactionConfig.CLEANER_COMMITS_RETAINED_PROP。该项的默认值是24,也就是说,其实Hudi默认就不会无限制地将数据膨胀下去(这显然很傻),而是最大保留最近24次的提交版本,也就是记录数据最近24次的变更。

我们可以将这个值改为1来测试一下这个配置项的作用。为了能准确看到文件数量的变化,我们特意准备一张数据量很少的表,当完成初始数据的写入时,磁盘上只生成一个parquet文件:

在这里插入图片描述
紧接着,我们修改原始数据,以upsert的方式重新插入这张表,我们会看到此时磁盘上将有两个parquet文件:
在这里插入图片描述
这符合hoodie.cleaner.commits.retained="1"的设置,因为当前也就只有两个commit,第一次的是要被保留的commit。

如果我们再次修改数据,再次以upsert的方式写入,我们会看到此时磁盘上还是只有两个parquet文件:
在这里插入图片描述
但只有一个是上次的,另一个是这次新生成的,而最早的那个parquet文件已经被删除了。这就表明保留的commit数量被严格限制为了1了,多余的commit都被自动清理了。


推荐:博主历时三年倾注大量心血创作的《大数据平台架构与原型实现:数据中台建设实战》一书已由知名IT图书品牌电子工业出版社博文视点出版发行,真诚推荐给每一位读者!点击《重磅推荐:建大数据平台太难了!给我发个工程原型吧!》了解图书详情,扫码进入京东手机购书页面!

在这里插入图片描述

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐