1 分钟读完

我宣布,Apache Kudu 项目,死了!

死了的 Kudu(非洲羚羊)

经过我的诊断(我曾修习过《洗冤集录》,《检验格目》等传统法医典籍,故有资格),它是死于 Apache Hudi 及其朋党之手,被活活砍死的!

本文是一篇法医报告,分析一下 Kudu 为什么被 Hudi 砍!死!了!。

Github Star: Kudu vs Hudi

免责声明:本报告乃本法医一家之言,读者「信不信由你」,如若将本报告呈于法庭审理,后果自担。

诞生

我们先来了解一下 Kudu 和 Hudi 诞生的背景。

Kudu 和 Hudi 是一母同胞。它们的「母亲」是基于 HDFS 构建的 Hive-like 数据仓库(e.g., Hive, Impala, Presto, HAWQ)。

这类数据仓库在典型批处理场景(包括跑批任务,交互式分析)下表现的还不错,但在实时场景,包括数据的实时摄入(流式的写入,大量 upsert 的场景;对数据新鲜度有影响),和查询的实时响应(尤其是点查或者小范围查询,其实也算是一种批处理)这两种场景下表现得难堪大用。后文为图简便,用 upsert 和点查代指这两种场景。

这种表现的一部分原因是由于它们的存储底座 HDFS 的特性导致的。HDFS 是一个「能力有限」的分布式文件系统,它只支持追加写文件,不支持随机的更新文件的某一段内容,因此,更新已有文件的一段内容,只能把整个文件拷贝并修改,再替换原有的文件。既然 HDFS 的更新成本如此高昂,这些 Hive-like 数据仓库想支持高效的 upsert,那就是非常不容易的了。于是这些数仓干脆躺平了,只支持数据的批量加载与更新,放弃支持流式地 upsert 了。

(笔者注:其实让 HDFS 支持随机更新并不难,但 HDFS 就是不做,并甩下一句:「爷傲奈我何」。)

另一方面,这类数据仓库也不支持细粒度(record-level)的索引,点查询和 upsert(要先点查是否存在再决定更新或插入)的性能自然也比较差。(尽管这些数据仓库有粗糙索引(每个文件中主键 min-max 统计信息)帮忙,但粗糙索引一是依赖 clustering,二是粗糙索引往往自身不做索引,读取需要全部扫描,在大数据体量下粗糙索引也会很大,扫描一遍不可避免的带来大量的时延)。

如果说 HDFS 的「能力有限」是导致它们如此表现的一部分原因的话,那另一部分原因则是这些 Hive-like 数仓系统没有绞尽脑汁的思考的复盘如何克服 HDFS 的这个缺陷,搞明白底层逻辑,形成新的顶层设计,完善方法论发力实时场景,完善生态,(此处省略 10w 字。。。)

大数据架构示例(Cassendra 可想象成 HBase)

由于 Hive-like 数据仓库只能支撑批处理场景,因此实时场景需要其他小伙伴的帮忙:

  1. 流计算引擎(e.g., spark/flink)做实时的流计算,并将结果同步到 HBase 之类的低延迟存储。– 流计算先于数据摄入到数据仓库就算好了,规避了 upsert 的问题。Hbase 支持低延迟访问,规避了点查的性能问题。(注:虽然 HBase 也是基于 HDFS 的,但它有「绞尽脑汁」的思考复盘过。)
  2. 流计算引擎会将上游的数据攒批后(或者不要流计算引擎,直接批量消费 Kafka 数据),写入 Hive-like 数据仓库。– 这均摊了拷贝并更新 HDFS 文件的代价,不过牺牲了数据的新鲜度(数据新鲜度一般是小时或者更差的级别),批处理的场景无法从 Hive-like 数据仓库享用到新鲜的数据,除非把增量数据暂存到 HBase 或其他系统,联邦查询一下。

我们通过引入流计算引擎和低延迟的存储来弥补 Hive-like 数据仓库的不足,以应对完整的业务场景。然而这套方案下来还是让人感到痛苦,这套方案

  1. 维护的组件过多,技术栈复杂,不好维护,我们不得不问,能不能少一两个组件?
  2. HDFS 上的数据,新鲜度不够,我们想要实现高新鲜度的批处理/交互式分析,还得联邦查询一下其他系统,这太蛋疼了!
  3. HDFS 上的数据,缺乏细粒度的索引无法实现低延迟的查询,实时分析方面做得还是太差。

Kudu 和 Hudi 在这个背景下诞生,它们的重要任务(之一)就是解决这些问题。

Kudu 简介

Kudu 性格比较刚,它为了解决这些问题,采用了「改朝换代」的方案,敢教日月换新天。

简单解释它的方案,就是 Kudu 认为,HDFS 太挫了,随机更新不行,分布式文件系统访问时延又高,我直接掀桌子,不玩了。

Kudu 不像其他人,它没有搞基于 HDFS 的 shared storage 架构,而是搞了一个 shared nothing 架构,试图自己实现支持高效 upsert/点查的存储引擎以取代 HDFS,问鼎大数据生态的存储底座。

Kudu 的架构如上图所示。Kudu 集群由两个子集群组成。

  1. 数据集群。一个基于 Raft 实现的分布式事务型列存引擎。集群中的数据被分片成一个个 tablet,每个 tablet 是一个 raft group。熟悉 TiKV 的小伙伴可以简单理解成一个列存版本的 TiKV。
  2. 元数据集群。负责集群的元数据(table schema,tablet distribution)信息存储,以及集群的一些管理调度工作(如 tablet rebalance)。注意,元数据集群只在一个专用 tablet 上,不支持分片,scalibility 稍微有点受限。

我们具体到单个 tablet 内部看一下。

Kudu 的存储采用的是 delta-main 的列存架构(可简单理解成一个只有 memtable 和 L0 的 LSM-tree)。

Kudu 增量数据的插入会写入到内存中面向写优化的行存(基于 MassTree 实现)的 MemRowSet,然后持久化 WAL 日志就算完成了。后续周期性地刷盘新生成一个新的面向读优化的列存 DiskRowSet(文件)。准确点说 DiskRowSet 是行列混存,也就是所谓的 PAX 格式。DiskRowset 中的数据被切分成一个个几百 K 的 block,block 内部按列存储。

对于特定 DiskRowSet 的更新,会先写入到它在内存中对应的 DeltaMemStore,同样持久化 WAL 日志就成。后续周期性地刷盘成为这个 DiskRowSet 的 REDO records(文件)。

Kudu 的读取需要合并 DiskRowSet 和 REDO records。

为了优化读性能,Kudu 还用到了以下手段:

  1. Compaction。周期性对 DiskRowSet 和 REDO records 文件做 compaction,以避免读取时需要合并 DiskRowSet 和多个 REDO records 文件。
  2. 文件级别索引。Kudu 中的表都是有主键的。然而,DiskRowSet 是按照时间周期性的刷盘的,DiskRowset 之间并没有按照主键排序。针对主键的查询,我们是没法知道它在那个 DiskRowSet 中的。于是 Kudu 增加了 DiskRowSet 文件级别的 min-max 统计信息,以及每个文件配备一个主键的 bloomfilter,用来在根据主键查询的场景快速过滤掉无用的 DiskRowSet。
  3. Record 级别索引。在生成 DiskRowSet 的时候,同时创建一个 DiskRowSet 内的 B-tree 索引。当我们根据手段 2 跳到 DiskRowSet 文件后,接下来就可以根据 DiskRowSet 内部的 B-tree 索引进一步定位到 block,大大提升根据主键的查询性能。
  4. Block cache。Kudu 的数据 block 比较小,为了优化查询性能,数据 block 会缓存在内存中,这类似于 HBase 的 block cache。

最后提一下,考虑到 Time Travel 和 Restore 需求,Kudu 还会为 DiskRowSet 保留旧版本数据到 UNDO records(文件)。

这里答一下问题,为什么 Kudu 解决了高效的 upsert 和点查问题?

  • 对于 upsert,Kudu 的写入是写到内存行存 memtable,并记录 WAL 日志。如果 Kudu 用 SSD 存储的话,就能做到百微秒级级时延了,比 Hive-like 数仓的不知道高效多少个数量级。
  • 对于点查,Kudu 有着文件级别和 tuple 级别从粗到细两种索引,性能出色。(畅想一下,要是 Kudu 再支持一下二级索引,TP 场景也能搞一搞,HTAP 指日可待?其实叫 HATP 更合适一些,因为 Kudu 中一等公民显然是 AP,二等公民才是 TP。)

当然,Kudu 做到了这些不是没有付出代价的,它的代价就是牺牲了一些大范围 scan 的性能,因为它在很多方面对点查的性能做了让步(如采用较小的 block size,破坏了列数据的局部性,削弱了按列压缩的能力,导致 scan 性能降低)。最终,我们看到的 Kudu,其实就是一个具备 HDFS 和 HBase 双重特性的产品,两方面能力都能兼顾一些(屏幕前的你小子可不要理解成两方面能力都差一些!)。

未完待续

由于时间关系(我这里已经是周日晚上 10 点了),本文暂时先写到这里(尽管我内心万般不愿),下周我会更新一下本文续集,介绍一下 Hudi,顺便向各位汇报一下 Kudu 的死因。

广告

各位读官如果觉得写得还不错,烦请关注一下我的知乎和微信公众号吧,搜索「黄金架构师」即可。谢谢支持~

我会持续创作数据库/大数据/云计算领域内容,定不负您小手点的那一下关注。

参考

  1. https://kudu.apache.org
  2. https://www.oreilly.com/library/view/getting-started-with/9781491980248/ch01.html

分类:

更新时间:

留下评论