QCon全球软件开发大会8折优惠倒计时最后3天,购票立减¥1760!了解详情 >>> 了解详情
写点什么

Apache Doris 在美团外卖数仓中的应用实践

2020 年 4 月 16 日

Apache Doris在美团外卖数仓中的应用实践

序言

本文侧重于以 Doris 引擎为“发动机”的数仓生产架构的改进与思考。在开源的大环境下,各种数据引擎百花齐放,但由于业务的复杂性与多样性,目前并没有哪个引擎能够适配所有业务场景,因此希望通过我们的业务实践与思考为大家提供一些经验参考。美团外卖数仓技术团队致力于将数据应用效率最大化,同时兼顾研发、生产与运维成本的最小化,建设持续进步的数仓能力,也欢迎大家多给我们提出建议。


数仓交互层引擎的应用现状

目前,互联网业务规模变得越来越大,不论是业务生产系统还是日志系统,基本上都是基于 Hadoop/Spark 分布式大数据技术生态来构建数据仓库,然后对数据进行适当的分层、加工、管理。而在数据应用交互层面,由于时效性的要求,数据最终的展现查询还是需要通过 DBMS(MySQL)、MOLAP(Kylin)引擎来进行支撑。如下图所示:



汇总数据的交互


业务团队日常经营分析最典型的场景就是各种维度下的自定义查询,面对如此灵活可变、所见即所得的应用场景,美团平台使用 Kylin 作为公司的主要 MOLAP 引擎。MOLAP 是预计算生产,在增量业务,预设维度分析场景下表现良好,但在变化维的场景下生产成本巨大。例如,如果使用最新商家类型回溯商家近三个月的表现,需要重新计算三个月的 Cube,需花费几个小时,来计算近 TB 的历史数据。另外,应对非预设维度分析,MOLAP 模型需要重新进行适配计算,也需要一定的迭代工作。


明细数据的交互


业务分析除了宏观数据之外,对明细数据查询也是一种刚需。通常大家会选择 MySQL 等关系型 DB 作为明细数据的快速检索查询,但当业务成长较快时,很快就会遇到性能瓶颈,并且运维成本也很高。例如,大数据量的同步、新增字段、历史数据更新等操作,它们的维护成本都非常高。


外卖运营业务特点

美团的使命是“帮大家吃得更好,生活更好”。外卖业务为大家提供送餐服务,连接商家与用户,这是一个劳动密集型的业务,外卖业务有上万人的运营团队来服务全国几百万的商家,并以“商圈”为单元,服务于“商圈”内的商家。


“商圈”是一个组织机构维度中的最小层级,源于外卖组织的特点,“商圈”及其上层组织机构是一个变化维度,当“商圈”边界发生变化时,就导致在往常日增量的业务生产方式中,历史数据的回溯失去了参考意义。在所有展现组织机构数据的业务场景中,组织机构的变化是一个绕不开的技术问题。此外,商家品类、类型等其它维度也存在变化维的问题。如下图所示:



数据生产面临的挑战

数据爆炸,每日使用最新维度对历史数据进行回溯计算。在 Kylin 的 MOLAP 模式下存在如下问题:


  1. 历史数据每日刷新,失去了增量的意义。

  2. 每日回溯历史数据量大,10 亿+的历史数据回溯。

  3. 数据计算耗时 3 小时+,存储 1TB+,消耗大量计算存储资源,同时严重影响 SLA 的稳定性。

  4. 预计算的大量历史数据实际使用率低下,实际工作中对历史的回溯 80%集中在近 1 个月左右,但为了应对所有需求场景,业务要求计算近半年以上的历史。

  5. 不支持明细数据的查询。


解决方案:引入 MPP 引擎,数据现用现算

既然变化维的历史数据预计算成本巨大,最好的办法就是现用现算,但现用现算需要强大的并行计算能力。OLAP 的实现有 MOLAP、ROLAP、HOLAP 三种形式,MOLAP 以 Cube 为表现形式,但计算与管理成本较高。ROLAP 需要强大的关系型 DB 引擎支撑。长期以来,由于传统关系型 DBMS 的数据处理能力有限,所以 ROLAP 模式受到很大的局限性。


随着分布式、并行化技术成熟应用,MPP 引擎逐渐表现出强大的高吞吐、低时延计算能力,号称“亿级秒开”的引擎不在少数,ROLAP 模式可以得到更好的延伸。单从业务实际应用考虑,性能在千万量级关联查询现场计算秒开的情况下,已经可以覆盖到很多应用场景,具备应用的可能性。例如:日数据量的 ROLAP 现场计算,周、月趋势的计算,以及明细数据的浏览都可以较好的应对。


下图是 MOLAP 模式与 ROLAP 模式下应用方案的比较:



MOLAP 模式的劣势


  1. 应用层模型复杂,根据业务需要以及 Kylin 生产需要,还要做较多模型预处理。这样在不同的业务场景中,模型的利用率也比较低。

  2. Kylin 配置过程繁琐,需要配置模型设计,并配合适当的“剪枝”策略,以实现计算成本与查询效率的平衡。

  3. 由于 MOLAP 不支持明细数据的查询,在“汇总+明细”的应用场景中,明细数据需要同步到 DBMS 引擎来响应交互,增加了生产的运维成本。

  4. 较多的预处理伴随着较高的生产成本。


ROLAP 模式的优势


  1. 应用层模型设计简化,将数据固定在一个稳定的数据粒度即可。比如商家粒度的星形模型,同时复用率也比较高。

  2. App 层的业务表达可以通过视图进行封装,减少了数据冗余,同时提高了应用的灵活性,降低了运维成本。

  3. 同时支持“汇总+明细”。

  4. 模型轻量标准化,极大的降低了生产成本。


综上所述,在变化维、非预设维、细粒度统计的应用场景下,使用 MPP 引擎驱动的 ROLAP 模式,可以简化模型设计,减少预计算的代价,并通过强大的实时计算能力,可以支撑良好的实时交互体验。


双引擎下的应用场景适配问题

架构上通过 MOLAP+ROLAP 双引擎模式来适配不同应用场景,如下图所示:



技术权衡


MOLAP:通过预计算,提供稳定的切片数据,实现多次查询一次计算,减轻了查询时的计算压力,保证了查询的稳定性,是“空间换时间”的最佳路径。实现了基于 Bitmap 的去重算法,支持在不同维度下去重指标的实时统计,效率较高。


ROLAP:基于实时的大规模并行计算,对集群的要求较高。MPP 引擎的核心是通过将数据分散,以实现 CPU、IO、内存资源的分布,来提升并行计算能力。在当前数据存储以磁盘为主的情况下,数据 Scan 需要的较大的磁盘 IO,以及并行导致的高 CPU,仍然是资源的短板。因此,高频的大规模汇总统计,并发能力将面临较大挑战,这取决于集群硬件方面的并行计算能力。传统去重算法需要大量计算资源,实时的大规模去重指标对 CPU、内存都是一个巨大挑战。目前 Doris 最新版本已经支持 Bitmap 算法,配合预计算可以很好地解决去重应用场景。


业务模型适配



MOLAP:当业务分析维度相对固化,并在可以使用历史状态时,按照时间进行增量生产,加工成本呈线性增长状态,数据加工到更粗的粒度(如组织单元),减少结果数据量,提高交互效率。如上图所示,由 A 模型预计算到 B 模型,使用 Kylin 是一个不错的选择。


ROLAP:当业务分析维度灵活多变或者特定到最新的状态时(如上图 A 模型中,始终使用最新的商家组织归属查看历史),预计算回溯历史数据成本巨大。在这种场景下,将数据稳定在商家的粒度,通过现场计算进行历史数据的回溯分析,实现现用现算,可以节省掉预计算的巨大成本,并带来较大的应用灵活性。这种情况下适合 MPP 引擎支撑下的 ROLAP 生产模式。


MPP 引擎的选型

目前开源的比较受关注的 OLAP 引擎很多,比如 Greenplum、Apache Impala、Presto、Doris、ClickHouse、Druid、TiDB 等等,但缺乏实践案例的介绍,所以我们也没有太多的经验可以借鉴。于是,我们就结合自身业务的需求,从引擎建设成本出发,并立足于公司技术生态融合、集成、易用性等维度进行综合考虑,作为选型依据,最终我们平台部门选择了 2018 年刚进入 Apache 社区的 Doris。



Doris 简介及特点

Doris 是基于 MPP 架构的 OLAP 引擎,主要整合了 Google Mesa(数据模型)、Apache Impala(MPP Query Engine)和 Apache ORCFile (存储格式,编码和压缩)的技术。


Doris 的系统架构如下,主要分为 FE 和 BE 两个组件,FE 主要负责查询的解析、编译、优化、调度和元数据管理;BE 主要负责查询的执行和数据存储。关于 Doris 的更多技术细节,可参考其官方文档



整体架构


Doris 的特点


  • 同时支持高并发点查询和高吞吐的 Ad-hoc 查询。

  • 同时支持离线批量导入和实时数据导入。

  • 同时支持明细和聚合查询。

  • 兼容 MySQL 协议和标准 SQL。

  • 支持 Rollup Table 和 Rollup Table 的智能查询路由。

  • 支持较好的多表 Join 策略和灵活的表达式查询。

  • 支持 Schema 在线变更。

  • 支持 Range 和 Hash 二级分区。


Doris 在外卖数仓中的应用效率


上图是我们在一个分析项目改造中的评估项目收益,整体在查询效率不变的情况下,生产耗能及存储成本都有较大收益。


以 20 台 BE+3FE 的 Doris 环境,效率、性能表现情况如下:


  1. 支撑数据分析产品数十个以上,整体响应达到 ms 级。

  2. 支持百万、千万级大表关联查询,同时进行维表关联的雪花模型,经过 Colocate Join 特性优化,可以实现秒级响应。

  3. 日级别,基于商家明细现场计算,同时满足汇总及下钻明细查询,查询时效基本都可以控制在秒级。

  4. 7 日趋势分析,2~3 秒。由于数据量较大,根据集群规模不同查询性能有所区别,但数据量较大时,调动的集群资源较多,因此 MPP 的并发性能受限于集群的性能。一般原则是并发较高的业务,需要严格控制查询时效(基本在毫秒级),对于并发不高的业务,允许进行较大的查询,但也要考虑集群的承受能力。

  5. 通过一年来的应用以及 Doris 的不断改进升级,Doris 的高可靠、高可用、高可扩展性也得到进一步验证,服务稳定可靠。


准实时场景下的应用

离线业务分析大多基于 T+1 的离线数据,但在营销活动场景下,外卖团队往往需要当日的实时数据进行业务变化的监控与分析,通常情况下会采用实时流计算来实现。


外卖实时业务监控有如下特点


  1. 避免分钟级的生产波动影响,业务上 10、15 分钟准实时数据可以满足分析需要。

  2. 实时数据需要与离线数据进行日环比与周同比的比对。

  3. 订单业务需要事件时间,体验业务需要生产时间,业务对齐逻辑复杂。

  4. 不同业务线需求差异大,指标需要良好扩展性。


由于业务上的复杂性,实时流计算中,需要考虑诸多业务口径的对齐,业务 ER 模型在合流处理中开发成本较高,资源占用较大,通过设计基于 Doris 的准实时生产数仓,可以灵活地实现业务微批处理,且开发生产成本都比较低。以下为基于 Doris 的准实时数仓架构设计,是典型的实时 Lambda 生产架构:



实现准实时计算方案,需要以下能力的支撑:


  • 实时的写入能力:目前支持 Kafka To Doris 秒级延迟。在可靠性、稳定性建设方面仍需进一步提升。

  • 引擎建设:短平快的计算+高效的存储性能。目前 Doris 引擎性能仍有进步空间,2020 年将有较大改进提升,随着后续 Page Cache,内存表等能力的上线,IO 将不再拖后腿,并发能力将有较大提升。

  • 可靠的调度能力:提供 5、10、15、30 分钟的调度保障能力。

  • Lambda 架构简化:实时数据与离线数据更好的在 Doris 中进行融合,灵活支撑应用。

  • 高效的 OLAP 交互:支撑业务的灵活查询访问,业务层通过视图进行逻辑封装直接复用汇总层多维模型,提高了开发效率,减少了运维成本。


相比 Storm、Flink 中的窗口计算,准实时 DB 微批的优势:



Doris 引擎在美团的重要改进

Join 谓词下推的传递性优化



如上图所示,对于下面的 SQL:


select * from t1 join t2 on t1.id = t2.id where t1.id = 1
复制代码


Doris 开源版本默认会对 t2 表进行全表 Scan,这样会导致上面的查询超时,进而导致外卖业务在 Doris 上的第一批应用无法上线。


于是我们在 Doris 中实现了第一个优化:Join 谓词下推的传递性优化(MySQL 和 TiDB 中称之为 Constant Propagation)。Join 谓词下推的传递性优化是指:基于谓词 t1.id = t2.id 和 t1.id = 1, 我们可以推断出新的谓词 t2.id = 1,并将谓词 t2.id = 1 下推到 t2 的 Scan 节点。这样假如 t2 表有数百个分区的话,查询性能就会有数十倍甚至上百倍的提升,因为 t2 表参与 Scan 和 Join 的数据量会显著减少。


查询执行多实例并发优化



如上图所示,Doris 默认在每个节点上为每个算子只会生成 1 个执行实例。这样的话,如果数据量很大,每个执行实例的算子就需要处理大量的数据,而且无法充分利用集群的 CPU、IO、内存等资源。


一个比较容易想到的优化手段是,我们可以在每个节点上为每个算子生成多个执行实例。这样每个算子只需要处理少量数据,而且多个执行实例可以并行执行。


下图是并发度设置为 5 的优化效果,可以看到对于多种类型的查询,会有 3 到 5 倍的查询性能提升:



Colocate Join


Colocate Join(Local Join)是和 Shuffle Join、Broadcast Join 相对的概念,即将两表的数据提前按照 Join Key Shard,这样在 Join 执行时就没有数据网络传输的开销,两表可以直接在本地进行 Join。


整个 Colocate Join 在 Doris 中实现的关键点如下:


  • 数据导入时保证数据本地性。

  • 查询调度时保证数据本地性。

  • 数据 Balance 后保证数据本地性。

  • 查询 Plan 的修改。

  • Colocate Table 元数据的持久化和一致性。

  • Hash Join 的粒度从 Server 粒度变为 Bucket 粒度。

  • Colocate Join 的条件判定。


关于 Doris Colocate Join 的更多实现细节,可以参考《Apache Doris Colocate Join 原理与实践》。


对于下面的 SQL,Doris Colocate Join 和 Shuffle Join 在不同数据量下的性能对比如下:


select count(*) FROM A t1 INNER JOIN [shuffle] B t5    ON ((t1.dt = t5.dt) AND (t1.id = t5.id)) INNER JOIN [shuffle] C t6    ON ((t1.dt = t6.dt) AND (t1.id = t6.id)) where t1.dt in (xxx days);
复制代码



Bitmap 精确去重


Doris 之前实现精确去重的方式是现场计算的,实现方法和 Spark、MapReduce 类似:



对于上图计算 PV 的 SQL,Doris 在计算时,会按照下图的方式进行计算,先根据 page 列和 user_id 列 group by,最后再 Count:



图中是 6 行数据在 2 个 BE 节点上计算的示意图


显然,上面的计算方式,当数据量越来越大,到几十亿几百亿时,使用的 IO 资源、CPU 资源、内存资源、网络资源会变得越来越多,查询也会变得越来越慢。


于是我们在 Doris 中新增了一种 Bitmap 聚合指标,数据导入时,相同维度列的数据会使用 Bitmap 聚合。有了 Bitmap 后,Doris 中计算精确去重的方式如下:



可以看到,当使用 Bitmap 之后,之前的 PV 计算过程会大幅简化,现场查询时的 IO、CPU、内存,网络资源也会显著减少,并且不再会随着数据规模而线性增加。


总结与思考

在外卖运营分析的业务实践中,由于业务的复杂及应用场景的不同,没有哪一种数据生产方案能够解决所有业务问题。数据库引擎技术的发展,为我们提供更多手段提升数据建设方案。实践证明,以 Doris 引擎为驱动的 ROLAP 模式可以较好地处理汇总与明细、变化维的历史回溯、非预设维的灵活应用、准实时的批处理等场景。而以 Kylin 为基础的 MOLAP 模式在处理增量业务分析,固化维度场景,通过预计算以空间换时间方面依然重要。


业务方面,通过外卖数仓 Doris 的成功实践以及跨事业群的交流,美团已经有更多的团队了解并尝试使用了 Doris 方案。而且在平台同学的共同努力下,引擎性能还有较大提升空间,相信以 Doris 引擎为驱动的 ROLAP 模式会为美团的业务团队带来更大的收益。从目前实践效果看,其完全有替代 Kylin、Druid、ES 等引擎的趋势。


目前,数据库技术进步飞速,近期柏睿数据发布全内存分布式数据库 RapidsDB v4.0 支持 TB 级毫秒响应(处理千亿数据可实现毫秒级响应)。可以预见,数据库技术的进步将大大改善数仓的分层管理与应用支撑效率,业务将变得“定义即可见”,也将极大地提升数据的价值。


参考资料


作者介绍


朱良,美团外卖数据仓库工程师。


凯森,Apache Kylin Committer,美团大数据工程师。


本文转载自公众号美团技术团队(ID:meituantech)。


原文链接


https://mp.weixin.qq.com/s?__biz=MjM5NjQ5MTI5OA==&mid=2651751555&idx=1&sn=1378e99a04641934b658e360fbe042e4&chksm=bd125dce8a65d4d8bd3ef00013c4dd8c5dc1a48ef534c2b344bb96491b42c60fbdfce6fdd16e&scene=27#wechat_redirect


2020 年 4 月 16 日 10:001893

评论

发布
暂无评论
发现更多内容

架构师训练营-大作业二

石子头

谬误词典:因果谬误

lidaobing

28天写作 谬误词典

生产环境全链路压测建设历程 26:FAQ之 压测结束阶段的相关问题

数列科技杨德华

28天写作

Spring Boot返回Json数据及数据封装

武哥聊编程

Java springboot SpringBoot 2 28天写作

现代浏览器原理

roadup

前端 浏览器 基础知识

如何让多个线程按顺序执行?

Java鱼仔

Java 多线程 高并发

读《专访朱啸虎》,我学到了什么?

李忠良

学习 写作 投资 创业者 读后感

架构师训练营 week12 学习笔记

花果山

Week 12 大数据应用

evildracula

学习 架构

架构师训练营 - 大作业(二)

树森

当目的地无法抵达「幻想短篇 3/28」

道伟

28天写作

Hadoop安装配置

小马哥

大数据 hadoop 28天写作

精选算法面试-栈

李孟

算法 堆栈 28天写作

python 变量

赵开忠

Python 28天写作

漫谈中台系列:《1小时带你深入理解中台》学习整理

程序员架构进阶

架构 中台 技术 探索与实践 28天写作

大作业

ABS

架构师训练营大作业(二)

Bear

架构师训练营第 1 期

大作业一

golangboy

架构师训练营第 1 期

架构师训练营 - 大作业一

石子头

28天瞎写的第二百一四天:考前临时抱佛脚

树上

28天写作

算法:罗马数字转换为整数,RxSwift的好处,git pull问题解决error: cannot lock ref,产品经理新人如何落地 John 易筋 ARTS 打卡 Week 34

John(易筋)

ARTS 打卡计划 算法:罗马数字转换为整数 RxSwift的好处 git pull cannot lock ref 产品经理新人如何落地

架构师训练营第 12 周:数据应用(一)

xiaomao

【架构师训练营 1 期】大作业一

诺乐

【架构师训练营 1 期】大作业二

诺乐

架构师训练营第十二周总结

xiaomao

架构师训练营 - 大作业(一)

树森

架构二期-第十二周作业(1)

浮生一梦

第十二周 2组 架构师训练营第2期

架构师训练营第 2 期 第12周总结

月下独酌

架构师训练营第2期

架构师训练营第十二周作业2

韩儿

架构师训练营 week12 课后作业

花果山

架构师训练营大作业(一)

Bear

架构师训练营第 1 期

移动应用开发的下一站

移动应用开发的下一站

Apache Doris在美团外卖数仓中的应用实践-InfoQ