技术专栏丨Carbondata研究与阶段性压测

技术专栏丨Carbondata研究与阶段性压测


一、CarbonData简介

Apache CarbonData 是一种有索引的列存储格式。它非常适合于做即席 OLAP 查询。因为独特的 MDK 索引设计,能达到的极好的剪枝效果。相比于 parquet 等其他的列存储格式,性能有极大的提升。

Apache CarbonData 是由华为贡献给 apache 社区,目前已经是 apache 顶级项目。CarbonData 目前应用于华为的多个解决方案中,用于分析运营商的海量的信令面、用户面、控制面的详单数据。详单数据数据量达到数千亿,每条记录都是多维度的。CarbonData 用于这些海量数据的实时聚合分析。

除了华为之外,在美团、滴滴、hulu 等公司的生产环境中也得到了使用。目前 CarbonData 项目 intel、ebay、VMWare、美团、Talend等公司也有人积极参与贡献。比如 CarbonData 的 flink connector、spark streaming connector 等功能都是由华为之外的其他人贡献的。

二、CarbonData架构

2.1. CarbonData文件格式

CarbonData 文件格式如下:

技术专栏丨Carbondata研究与阶段性压测

一个 HDFS block 中会分为多个 blocklet。Blocklet 是文件内的列存数据块,是最小的 IO 读取单元。Column chunk 是 Blocklet 内的列数据。Page 是 Column chunk 内的数据页,是最小的解码单元。

File header 中存放元数据信息,包括 version 和 schema。

Footer 中存放 Blocklet offset、索引、统计信息。统计信息包括 blocklet的 min 和 max, page 的 min 和 max。索引存放的是 blocklet 的 startkey 和 endkey。

下图更为详细:

技术专栏丨Carbondata研究与阶段性压测

2.2. MDK索引原理

技术专栏丨Carbondata研究与阶段性压测

CarbonData 索引叫做 MDK 索引,即 Multi Dimension Key。如上图所示,year,Quarter,month,territory,country 这五个是 dimension,quantity 和 sales 是度量。维度进行字典编码,并对进行排序。然后存放到 blocklet 中。

存放于 blocklet 时,会同时把刚才提到的 startkey 和 endkey 存放好。如下图所示:

技术专栏丨Carbondata研究与阶段性压测

2.3. 索引查找过程

技术专栏丨Carbondata研究与阶段性压测

CarbonData 有两级索引。第一级索引是 block index ,存放于 spark driver 中。是一个 global B+ 树。使用这个索引避免扫描不必要的文件,可以减少95%的扫描量。

第二级索引是 blocklet 索引,用于过滤掉不必要的 blocklet。

一个完整的过滤如下图所示:

技术专栏丨Carbondata研究与阶段性压测

以我们的测试结果为例,我们的 action 表是18.55亿条记录,我们的 profile 表是415万条记录。做一个复杂的查询,做3个join和3个 group by。CarbonData 需要扫描的数据量仅为53.1 MB,而 parquet 需要扫描的数据量则为 5.5G。而且 action 表数据量翻了3倍,CarbonData 需要扫描的数据量仍然为 53M。所以说,数据量越大,CarbonData 相比 parquet 的性能优越性越大。

CarbonData:

技术专栏丨Carbondata研究与阶段性压测

Parquet:

技术专栏丨Carbondata研究与阶段性压测

2.4. CarbonData其他优化

CarbonData 还有些其他优化,这里只简单列举。延迟解码、向量化处理、预聚合表、partition 表(比 hive/spark 中的 partition 功能要强大很多,可以理解为索引,这里不详细讲解)、compaction、bucket、segment(我理解 segment 对优化意义不大,partition 更强大)等等。

2.5. CarbonData中对我们有用的新功能

Streaming Ingestion

目前支持 spark structured streaming,可以支持流式处理完数据后流式写入到 CarbonData 表中,这个功能是对我们有用的,需要后续研究。

Update &delete

CarbonData 目前支持 update 和 dalete。对我们也是有意义的。经过测试,update 可以运行,但是结果不对。可能需要跟社区讨论。

三、我们的性能测试结果

环境:

用了3台 40C128G,磁盘的 iops 在2000多。

不过我没用全部,总共用了 91vcore 264 GB。

第一次性能测试:

Action 表6亿多,profile 表200多万。从 ES 中通过代码导入到 CarbonData 中。

测试例子:

按学历统计近半年事件“event7”的触发次数。

且触发此事件的访客的性别需要为男,最近所在城市为“北京”;

且触发此事件的访客最近一个月访问了“com.android.dazhihui.view.screen.NewInitScreen10”活动页面(至少有1次访问时长超过10s);

且触发此事件的访客最近一周触发了“event7”事件(至多触发100次 label 为“label8”)

该语句翻译为了3个 join 和3个 group by。

需要8s左右,scan 数据量为 53M。

第二次性能测试:

Action 表18.55亿,profile 表415万。从 ES 中通过代码导入到 CarbonData 中。

语句同测试一。

该语句翻译为了3个 join 和3个 group by。

还是需要8s左右,scan 数据量仍然为 53M。

第三次性能测试:

在第二次性能测试基础上,同时并发6个同样的查询。

每个查询在8s-14s之间,性能稳定。

相比 ES 的存储,CarbonData 只使用约8.X%的存储。

四、Streaming ingest

把es的数据导出为 parquet,然后使用 structured streaming 流式写入到 CarbonData 中。经过调试,最终能调试通过。使用1个 executor 2C6G 进行性能测试。1S能够写入10万条记录到 CarbonData中。性能还是不错的。

同时,CarbonData 也支持 spark streaming ingest。

五、Update

CarbonData 有 update 的能力。但是 CarbonData 的目标是 OLAP/small scan/full scan。不适合于做 OLTP。

所以 profile 功能不能直接部署于CarbonData.目前想到的办法是 profile 功能放到 kudu 中。然后从 kudu 中周期性加载到 CarbonData 中。这个功能后续还需要继续研究。

六、兼容性

CarbonData 是基于 spark。CarbonData 1.3 可以兼容 spark 2.1 和 spark 2.2。

只要大数据发行版支持 spark 2.1 和 spark 2.2,就可以兼容 CarbonData.

1)与 CDH 兼容性

CDH 版本和 spark 是松耦合的。CDH 出的 spark 2 parcel 包可以用于多个 CDH 版本。

同时,CDH 还可以支持 apache spark 作为他的 gateway。

所以 CDH 与 CarbonData 是兼容的。

2)与华为兼容性

华为 fusioninsight 本身就包含 CarbonData。

所以华为与 CarbonData 是兼容的。

3)与星环兼容性

星环中包括两个 spark。Inceptor 是他们的定制 spark。

Discover 是完全开源的 spark。

我们 的CarbonData 可以运行于 discover spark 之上。

七、后续工作

后续还要增加工作:

action 表记录数达到百亿级别,继续进行性能测试。

目前我觉得应该还有性能优化的空间。


分享到:


相關文章: