OLAP 演进实战,Druid 对比 ClickHouse 输在哪里

​导读

本文介绍 eBay 广告数据平台的基本情况,并对比分析了 ClickHouse 与 Druid 的使用特点。
基于ClickHouse表现出的良好性能和扩展能力,本文介绍了如何将eBay广告系统从Druid迁移至ClickHouse,希望能为同业人员带来一定的启发。

背景

eBay广告数据平台为eBay第一方广告主(使用Promoted Listing服务的卖家)提供了广告流量、用户行为和效果数据分析功能。

广告卖家通过卖家中心(Seller Hub)的营销标签页、效果标签页和公开API,有效掌控和对比店铺的营销活动和推广商品的流量、销量的实时和历史数据,并通过网页或者API 下载数据分析报告。

这一系统上线之初使用了自研的分布式SQL引擎,构建在对象存储系统之上。3年前随着广告流量增加,我们把数据引擎切换到Druid上。

这一平台的主要挑战如下:

  • 数据量大 :每日的插入数据记录有数百亿条,每秒的插入峰值接近一百万条;
  • 离线数据摄入 :在不影响实时数据摄入的情况下,每天需要对前1-2天的数据进行在线替换。根据上游数据团队发布清洗过的每日数据,广告数据平台需要在不影响查询的情况下每日替换实时数据,数据切换要求实现跨节点的全局原子操作;
  • 完整性和一致性:面向卖家的财务数据,离线更新后的数据要求不能有遗漏和重复;实时数据要求端对端的延迟在十秒内。

Druid 对比 ClickHouse

Druid 于 2011 年由 Metamarkets 开发,是一款高性能列式在线分析和存储引擎。

它于2012年开源,2015年成为Apache基金会旗下项目。Druid在业界使用广泛,为千亿级数据提供亚秒级的查询延迟,擅长高可用、水平扩展;另外为数据摄入提供了很多非常方便的聚合、转换模版,内建支持多种数据源,最快可以在几十分钟内配置好新的数据表,包括数据定义和数据摄入链路(Lambda 架构),大大提高了开发效率。

ClickHouse 由俄罗斯最大的搜索引擎公司 Yandex 研发,设计目标是支持 Yandex.Metrica(世界第二大Web分析平台)生成用户分析报表等核心功能。ClickHouse是一个数据库管理系统(DBMS),有数据库、表、视图、DDL、DML等概念,并提供了较为完整的SQL支持。其核心特性有如下几点:

  • 高效的数据存储 :通过数据压缩和列式存储,可以达到最高10倍的数据压缩率;
  • 高效的数据查询 :通过主键索引、向量化引擎处理、多处理器并发和分布式查询,最大压榨CPU的所有能力,在中小规模的数据量上尤为突出;
  • 灵活的数据定义和 :通过支持SQL语言、JDBC和关系模型,降低学习和迁移成本,可以和其他现有数据的产品无缝集成。
    为什么迁移? 运维

Druid虽然提供了很多非常方便的数据摄入功能,但它的组件构成也较为复杂,节点类型有6种(Overload, Coordinator, Middle Manager, Indexer, Broker和Historical)。

除了自身的节点,Druid还依赖于MySQL存储元数据信息、Zookeeper选举Coordinator和Overlord、HDFS备份历史数据。

ClickHouse的架构采用了对等节点的设计,节点只有一种类型,没有主从节点。如果使用了副本功能,则依赖于Zookeeper保存数据段的同步进度。

与此同时,eBay的基础架构团队提出在定制ClickHouse的基础上,向产品团队提供列式数据库存储的服务。除了运维和生命周期管理,基础架构团队对ClickHouse进行改造和二次开发,进一步提高了数据摄入和存储的效率,并在离线摄入方面弥补了和Druid的功能差距。

延时数据插入

Druid通过引入实时数据的索引任务,把实时数据处理成一个个分段数据(segment),并归档成历史数据。成为分段数据之后,该时段数据即不可写入。由于并发实时索引任务数的限制,我们设置了3个小时的窗口长度(每个小时一个任务),因此超过3个小时的数据就无法写入。

在某些极端情况下,例如上游数据延迟或者实时数据消费过于滞后,就会导致离线数据替换前这部分数据的缺失。ClickHouse则没有这个限制,任意分区都可以随时写入。

主键优化

ClickHouse支持的主键并不是传统意义下关系型数据库的主键。传统的主键要求每条表记录都有唯一的键值,通过查询主键可以唯一地查询到一条表记录。而在ClickHouse中,主键定义了记录在存储中排序的顺序,允许重复,所以称之为排序键似乎更加合理。

事实上在ClickHouse里的主键定义通过ORDER BY声明,仅在个别场景中允许和排序键不一致(但必须是排序键的前缀)。

由于我们的产品是给卖家提供分析功能,几乎所有的查询限定在了单一卖家维度,因此通过主键按照卖家排序,可以极大地提高查询效率以及数据压缩率。

系统架构

如上图所示,系统由4个部分组成:

  • 实时数据获取模块,接入eBay的行为和交易实时消息平台;
  • 离线数据替换模块,接入eBay内部的数据仓库平台;
  • ClickHouse部署和外围数据服务;
  • 报表服务,支撑广告主、商家后台和eBay公开API。

实战经历

Schema 设计

ClickHouse提供了丰富的schema配置。这方面需要根据业务场景和数据模式反复斟酌和多次试验,因为不同的选择会对存储和性能有数量级的影响,一个错误的选择会导致后期巨大的调优和变更成本。

1)表引擎

ClickHouse的存储引擎的核心是合并树(MergeTree),以此为基础衍生出汇总合并树(SummingMergeTree),聚合合并树(AggregationMergeTree),版本折叠树(VersionCollapsingTree)等常用的表引擎。另外上述所有的合并树引擎都有复制功能(ReplicatedXXXMergeTree)的对应版本。

我们的广告数据平台的展示和点击数据选择了复制汇总合并树。这两类用户行为数据量极大,减小数据量节省存储开销并提升查询效率是模式设计的主要目标。ClickHouse在后台按照给定的维度汇总数据,降低了60%的数据量。销售数据选择了普通的复制合并树,一方面由于销售数据对某些指标有除汇总以外的聚合需求,另一方面由于本身数据量不大,合并数据的需求并不迫切。

2)主键

一般情况下,ClickHouse表的主键(Primary Key)和排序键(Order By Key)相同,但是采用了汇总合并树引擎(SummingMergeTree)的表可以单独指定主键。把一些不需要排序或者索引功能的维度字段从主键里排除出去,可以减小主键的大小(主键运行时需要全部加载到内存中),提高查询效率。

3)压缩

ClickHouse支持列级别的数据压缩,显著地减少原始数据的存储量,这也是列存储引擎的巨大优势。查询阶段,较小的存储占用也可以减少IO量。对不同列选择一种合适的压缩算法和等级,能把压缩和查询的平衡做到性价比最优。

ClickHouse的所有列默认使用LZ4压缩。除此以外,一般的数据列可以选择更高压缩率的算法如LZ4HC,ZSTD;而对于类似时间序列的单调增长数据可以选择DoubleDelta, Gorilla等特殊压缩算法。LZ4HC和ZSTD等高压缩率的算法还可以自己选择压缩级别。在我们的生产数据集上,ZSTD算法对String类型字段压缩效果较为显著。LZ4HC是LZ4的高压缩比改进版,更适用于非字符串类型。

更高的压缩率意味着更少的存储空间,同时由于降低了查询的IO量,可以间接提升查询性能。不过CPU也不是大风刮来的,数据的插入性能就成了牺牲品。根据我们内部测试的数据,在我们的生产数据集上使用LZ4HC(6)相比LZ4可以节省30%的数据,但实时数据摄取性能下降了60%。

4)低基

值得一提的是,对于基数较低的列(即列值多样性低),可以使用LowCardinality来降低原始存储空间(从而降低最终存储空间)。如果在使用压缩算法的情况下对一字符串类型的列使用LowCardinality,还能再缩小25%的空间量。

在我们的测试数据集上,如果整表组合使用LowCardinality、LZ4HC(6)和ZSTD(15),整体压缩比大约在原来的13%左右。

离线数据替换

1)挑战

针对广告主的数据报表要求数据准确、一致。实时的行为数据存在少量的bot数据(需要离线清除),另外广告的归因也需要在离线阶段重新调整,因此我们引入了离线数据链路,在实时数据写入24-72小时之后,用离线数据替换实时数据。其中的挑战如下:

  • 广告系统每天需要处理的用户离线数据量近1TB,在此之前,需要耗费大量时间将数据从Hadoop导入Druid。另外,导入期间的I/O、CPU和内存的开销对查询的压力不小。如何在保证数据一致性的同时,亦确保数据迁移的效率,是问题的关键;
  • 如何在数据替换期间,确保用户可见的数据波动最小。这就要求数据替换操作是原子性的,或者至少对每个广告主都是原子的;
  • 除了日常的离线数据更新,在数据仓库数据出现偏差遗漏时,需要支持大范围的数据修正和补偿。作业调度要求保证日常工作及时完成,并尽快完成数据修正工作。此外还需要监控数据更新中的各种指标,以应对各种突发状况。

Druid原生支持数据离线更新服务,我们与基础架构团队合作,在ClickHouse平台实现了这一功能。