快手 OLAP 系统为内外多个场景提供数据服务,每天承载近 10 亿的查询请求。原有湖仓分离架构,由离线数据湖和实时数仓组成,面临存储冗余、资源抢占、治理复杂、查询调优难等问题。通过引入 Apache Doris 湖仓一体能力,替换了 Clickhouse ,升级为湖仓一体架构,并结合 Doris 的物化视图改写能力和自动物化服务,实现高性能的数据查询以及灵活的数据治理。
ToB 系统:商业化报表引擎、商业化 DMP、商业化磁力金牛、电商选品等
内部系统:KwaiBI、春节/活动大屏、APP 分析、数据同步、用户理解中心、APM、CDN 监控、雷达监控系统等
存在的问题
冗余存储:虽然将数据入仓到 ClickHouse 能够提高查询性能,但同时导致了数据冗余存储,影响数据就绪时间和存储效率。
资源占用:to ClickHouse 过程也会占用 ClickHouse 集群资源,不仅体现在 Clickhouse 中数据同步系统的资源消耗,且在数据写入后,ClickHouse 内部也有 Compaction 等计算资源的消耗,在高并发查询的时候,并行读写带来更显著的资源抢占问题,可能影响其他查询任务的执行效率和集群的整体性能。 治理复杂:数据工程师需要投入大量人力建立 ADS 层模型,以支持 to ClickHouse 导入工作,并需要投入额外的精力维护导入任务。此外,当报表看板下线后,对应 ADS 层和 to ClickHouse 任务还在运行,造成计算和存储资源的不必要浪费,大部分情况下需要依赖人工介入判断并终止这些任务,这无疑增加了运维管理的复杂度。
升级目标及选型
极致分析性能、助力湖仓查询加速:借助强大的分布式 SQL 查询引擎,Apache Doris 对 Parquet、ORC 等开发格式进行了深度适配。凭借灵活的缓存策略和物化视图能力,用户可直接在湖仓数据之上架设 Apache Doris,从而实现高吞吐和低延迟的数据分析能力。
多源联邦分析、消除数据孤岛:Apache Doris 提供丰富的数据源连接器,可以对各种异构数据源如 Hive、Iceberg、Hudi、关系型数据库进行统一的元数据管理和映射,并可通过标准 SQL 语言进行联邦分析。 湖仓数据无缝集成、自由流转:结合 Doris 异步物化视图能力和内置作业调度功能,用户可以便捷的基于 Doris 对湖仓数据进行分层加工处理,从而简化湖仓数据处理的复杂度。 统一数据湖的构建和计算引擎:Apache Doris 支持主流湖仓的数据写入能力,用户可以基于 Doris 进行统一的数据写入、处理及分析,形成湖仓一体架构下的链路闭环。同时,基于 Arrow Flight 协议的高速数据通道,也进一步提升了 Doris 数据格式的开放性,用户可以在 Doris 上使用其他计算引擎支撑更丰富的计算负载。
基于 Apache Doris 的湖仓一体架构
数据加工层:数据源数据同步到数据湖仓(Hive/Hudi),并在湖仓系统中完成从 ODS 层到 DWS 层的加工处理, DWS 层到 ADS 层依赖自动物化服务实现(后文详细介绍)。
数据缓存层:ADS 层数据缓存到 Alluxio 中,以提供高性能的数据缓存访问能力。同时,元数据也缓存到元数据管理服务中,以提供统一的、稳定的元数据访问服务。 数据查询层:基于 Apache Doris 提供对 ADS 层数据的高性能查询服务。
查询路由服务:通过分析和预估查询的数据扫描量,将超大查询自动路由到 Spark 引擎,以避免大查询占用过多的 Doris 资源。
自动物化服务:提供 DWS 层到 ADS 层按需自动化加工,智能选择排序字段、哈希字段以及更合理的物化,从而实现对复杂查询或高优看板数据的智能查询加速。
统一存储、简化链路:Doris 可以直接访问湖仓数据。Hive ADS 层的数据不再需要额外导入和存储在 OLAP 系统中,降低了数据维护和存储的成本,同时缩短了数据链路,提升了数据时效性。
查询性能提升:Apache Doris 本身作为高性能的计算引擎,查询性能已有较大的提升。同时结合 Doris 自身的物化视图透明改写能力,以及基于代价的查询优化器能力,可以满足不同数据分析场景下的查询加速需求。 更灵活的数据治理:结合 Doris 的物化视图改写能力和自动物化服务,可以更方便的在 ADS 层进行视图建模,对业务层屏蔽屏蔽复杂的底层实现逻辑。
缓存服务与优化
湖仓一体架构下,缓存层主要用于避免远程数据访问可能发生的网络延迟高、网络抖动、带宽不足等问题,提升数据访问的性能和稳定性。缓存的内容大致可以分为元数据缓存和数据缓存。针对这两种缓存,快手结合 Doris 的系统架构和特性做了适配和优化。
01 元数据缓存
02 数据缓存
is_cached
字段判断数据是否已经被缓存,并自动选择从 Alluxio 或者 HDFS 中读取。03 优化效果
自动物化系统
ADS 模型消费:主要由运营、产品、数据分析和业务研发团队使用,这些需求与业务场景深度耦合,呈现出多样化的特点。
ADS 模型生产:由数据工程师负责,他们需要深入理解业务需求,设计相应的 ADS 模型并进行生产加工,这给工程师带来了较大的理解成本。
数据工程师将所有数据直接交付至 DWS 层。
消费者访问 DWS 层数据表,并基于 DWS 层进行看板和报表的配置。 ADS 层实现自动物化,提供实际的数据访问,物化视图的生产逻辑对数据工程师屏蔽,全部托管在计算引擎 中。 Doris 根据查询自动选择最优的物化视图,从而实现查询加速。
物化视图的生成需要大量计算资源。快手每天处理的数据量庞大,涉及数十万张表、数百 PB 的数据增量。如果全部由 Doris 处理,将消耗大量计算资源。因此,利用现有的计算集群资源(如 Spark)可以有效降低计算成本。
高优看板数据就绪需要 SLA 保障,因此物化视图的调度必须和其他系统交互,使用 Doris 内置调度方案需要对内核修改,具有较高的侵入性。 出于整体系统设计考虑,物化视图必须统一闭环到数据湖上,因此其数据必须保存在外表中。而 Doris 的物化视图目前是通过内表形式存储,以确保最佳查询效率。 Doris 内置的物化视图透明改写能力在未命中物化视图时,会降级到原表查询。然而,快手的降级策略要求将这类查询转向 Spark,以避免占用过多的 Doris 计算资源,因此需要引入额外的代码逻辑。
充分利用 Doris 优化器的视图改写能力,实现灵活的查询改写功能。
利用外部系统实现物化视图生产、管理等过程,使得 Doris 能够更合理的利用计算资源,灵活对接内部服务。
01 物化发现
专家规则:用户主动提供一些维度、指标列的定义,或通过 SQL 样例推导指标列和维度列。
维度定义,如 city
,gender
等。指标定义,如 sum(time)
,count(distinct uid)
等。SQL 样例,如 select sum(time),count(distinct uid) from db.tbl group by city, gender
;分析历史查询:基于历史查询,自动发现物化定义。
识别出全局高频查询算子进行物化,尽可能提高物化复用率。 除了聚合指标维度,还可以自动设置索引、引利分桶字段等。
02 物化生产
03 物化消费
KwaiMTMV
的物化视图对象。在查询改写阶段,扩展了 Doris 的物化视图改写能力,使其能够识别KwaiMTMV
类型的物化视图,并进行查询改写。author_id
指标进行去重的外表查询的改写结果示例。可以看到 Doris 将count distinct
算子改写为了更高效的 Bitmap 算子,并将目的表改写到了合适的物化视图表上。04 使用效果
湖仓数据查询优化
外表统计信息:统计信息对查询规划尤为重要,尤其是在复杂关联查询中。然而,外表统计信息存在收集成本较高,各数据源的统计信息类型和统计口径各不相同的问题。为解决该问题,可在 Spark 进程处理湖仓数据时,同步收集统计信息并将其存储在 Meta Server 中,Doris 可以直接访问这些统计信息,从而为查询优化器提供最优的查询计划。
有序文件和合适的 RowGroup 大小:在构建 Parquet 数据时,按主键排序可以确保文件数据有序。这使得谓词下推时能够最大程度地过滤无用的 RowGroup。同时,指定合适的 RowGroup 大小可以有效提高 RowGroup 的过滤率。 使用 Bucket 表:湖中的表可以按规则生成分桶(Bucket)表。Doris 利用分桶信息生成 Colocation Agg 和 Colocation Join 等优化的分布式执行逻辑,避免大量的数据 Shuffle,从而提高查询效率。
结束语
公司内部的看板、报表场景将逐步由 Hive to Clickhouse 替换为 Doris 湖仓一体架构,以提升数据处理效率和查询性能。
即席查询(AD-Hoc)场景将逐步从 Presto 迁移到 Doris,并将所有分析引擎统一为 Doris,以简化技术架构并增强数据分析能力。