本文内容来自 Community Over Code Asia 2025 大会 OLAP & Data Analysis track 分享议题。本文主要介绍了 Apache Doris 在菜鸟的大规模落地的实践经验,数据分析已经渗透到每个业务线的同学,每天在不同的数据分析报表、数据产品上查数和用数,OLAP 数据库在其中承担着重要作用。我们为什么选择 Doris,以及 Doris 如何在菜鸟从 0 开始,一步步的验证、落地,到如今上万核的规模,服务于各个业务线,Doris 已然成为菜鸟 OLAP 的最优选型。
本文目录预览如下:
菜鸟成立于 2013 年,是电商物流行业的全球领导者。
菜鸟的实时数据架构经过最近 3 年的优化和迭代,在选型上已经逐步收敛。
面向成本友好型的 OLAP 选型,一直是大家探讨最多的话题,尤其在菜鸟仓储业务,在成本和稳定性上是非常痛的一个点,最近几年除了做精细化的集群治理,还要面向业务做合理的数据架构,在这上面我们投入了很大的精力,但在成本和稳定性上均无法达到预期的终态,所以我们在早期也同步在积极探索更高性价比的 OLAP 选型。
而 2 年前,Doris 逐渐走入到我们的视野。 作为 Apache 软件基金会的顶级项目,Apache Doris 在开源持续性方面具有显著优势:一方面,Apache 基金会的治理模式确保了项目的长期稳定发展和社区驱动的创新;另一方面,开源的透明性让我们能够深入了解技术架构,避免厂商锁定风险,同时活跃的 Doris 社区也为我们提供了丰富的技术支持和最佳实践分享。
在前期我们做了大量的调研和性能以及稳定性测试,面向业务视角,成本和稳定性的最重要的两个指标,面向我们自己,运维效率是首要关注的指标,这涉及到未来的大规模推广和部署,而 Doris 在这三项指标上,均超出我们的预期。
值得一提的是,物流数据主要来源于 OLTP 数据库的实时同步,其中的业务数据持续更新(如订单状态变更、物流轨迹跟踪、库存变动等)、查询实时性要求高、业务场景复杂等特点,传统批处理 OLAP 系统难以满足这些需求,而 Doris 的实时更新能力恰好解决了这些痛点:
Doris 默认所有场景都采用 MOW(Merge-on-Write)模式,结合 Delete Bitmap + Primary Index 技术实现。相比传统 Copy-on-Write 机制,MOW 模式通过 LSM tree 数据组织和主键索引优化,在写入阶段为旧数据打上删除标记,查询时直接跳过已标记删除的数据行,无需实时计算删除逻辑。这种设计使得大部分场景下数据写入后可在秒级可见,查询响应时间稳定在百毫秒以内,足以支撑物流场景对实时性的要求。比如补货业务的延迟要求基本都在 1 到 2 秒内数据需要可见。(对延迟要求不高的,Doris 一般 10 秒内可见)
核心业务场景的应用价值 :
通过 Doris 的实时更新能力,菜鸟物流不仅提升了业务响应速度,也为构建面向用户的实时数据服务奠定了技术基础。这些技术优势是我们选择 Doris 作为 OLAP 最优选型的重要考量因素。
Doris 在菜鸟的这 2 年,从时间轴看,其实走得并不快,我们没有急于求成,而是确定好每个里程碑,把每个时间节点把控好,做到极致。可以看到在 2023 下半年,我们只做了一件事,选一个代表性的核心场景做验证,开始并没有选择在小场景做验证的原因是,如果在最重要的核心场景都无法验证通过,那基本不可能推动业务侧做后续的迁移。在 2023 年的双 11,我们第一个小集群完成大促的验证,当时这个集群规模只有 300 多 CU。核心场景验证通过后,2024 年新财年伊始,我们确定了 Doris 大规模推广的计划和方案,内部完成项目 KO。
9 月首批核心集群全部完成迁移,11 月第一次大规模部署征战双 11,在成本和稳定性上均表现出色。截止到目前,Doris 在菜鸟已经有 25+ 集群,遍布 3 个地域(已具备全球化多地域部署能力),日常上万核的规模,整个迁移过程,未发生一起线上故障。在应用场景上,除了 OLAP 分析,菜鸟也探索应用了 Apache Doris + Apache Paimon 的湖仓一体解决方案。
在最开始的验证上,我们选择了仓内数据产品使用频率最高的包裹生产进度场景,这个场景的主要用于仓库的生产进度监控,订单结构分析,出库达成监控,排班排产等生产场景。此场景是比较典型的多表级联的 AD-HOC 场景,涉及到的维度指标组合很多以及多张亿级别大表 Join,并且对稳定性的要求也是极高,不能容忍出现数据延迟,查询超时,否则极易造成故障。
在验证过程中,我们先选择了新老集群双跑方案,并没有急于做灰度切流的方式,我们利用流计算的能力,1:1 回放线上 SQL,验证 SQL 的查询 RT 是否达到预期,以及语法上的兼容性。持续跑了一段时间后,才开始进行仓粒度的灰度切流。灰度切流的过程中,逐步对 Doris 集群扩容,直至 100%流量全部切到 Doris。
凭借 Doris 其完整的实时更新技术,在菜鸟物流场景中展现了卓越的性能表现:
在包裹生产进度这个场景,我们取得了阶段性的成果,在成本和性能上远超我们的预期,成本上降低了 90%,平均 RT 降低 72%。
在核心场景的成功验证后,我们着手开始为大规模迁移做事前的准备工作,主要工作归纳为六大类:
在语法兼容这块,最初的方案考虑到业务存在较多 SQL 改写的成本,想在数据服务层中做适配,做方言的转换,但实际操作下来,我们 case by case 分析后,发现语法不兼容的种类没有想象中的多,所以我们选择了投入成本更低的方式,我们将这些语法不兼容的问题全部梳理归类,给出改写建议,业务侧只需按 case 改写即可。
如果遇到语法不支持的,无法改写的,只能进行二开,比如业务场景用的最高频的 case 就是多值列,类似指定分隔符拼接的一个字符串,用户可以任意匹配分隔后的一个或多个。在原存储中有明确的数据类型和语法支持,而在 Doris 中,最开始我们考虑使用数组或正则替换,但性能和稳定性无法满足预期,而能够最优适配的只有倒排索引的检索函数 match_any | all | phrase,但目前倒排索引不支持按照指定分隔符分词,为了满足业务场景,我们在倒排索引分词器的基础上增加了指定分隔符分词并构建倒排索引的能力,最终完成这一语法的支持。
数据导出是业务侧每天都要使用的一个高频场景,用于做数据分析,我们有统一的导出服务,会对接底层的存储,在原存储上也类似使用 select into 到 oss 的方式,所以在 Doris 上,我们也要优先支持这一能力,但在测试的时候发现导出的中文全是乱码,并且官方文档中也并没有相关的编码参数可以配置。查看 Doris 输出 OSS 部分的源码, Content-Type 设置的为 application/octet-stream,octet-stream 是通用的二进制流类型,用于表示未知或非标准格式的文件,如果文件流中未显示指定编码格式,excel 打开会乱码。所以我们在输出流增加了 bom 头标记来解决此问题。
在原存储未开放可用的 Source connector 和日志的条件下,进行全量数据同步是我们比较头疼的点,我们采用了两种方式:
且物流行业的数据写入呈现出独特的特征:不但并发比较高(单表就可达 5 万行/S),而且字段数较多(通常 300-400 个字段)。这种"宽表"的写入模式对数据库的实时更新能力提出了特殊要求。Doris 凭借其 LSM tree 数据组织方式和 Delete Bitmap 标记删除机制,能够高效处理这类场景:
如何减少日常和高频大促的繁重运维工作,是我们保障所有集群长期稳定性最重要的职责。物流行业业务复杂并且多元化,背靠前台的电商业务,会有频繁的大促,业务对稳定性的要求很高,已经不是一个纯粹简单的数据分析引擎,在业务全链路各个环节都承担的重要作用。所以可以把整个运维工作分成三大类:
第一类是摆脱人肉运维,比如我们每个月可能都有大促,所以会有频繁的扩缩容需求。
第二类是定规范,收口所有对集群不稳定的高频操作,比如导入和删数据。
第三类是优化集群结构,在集群建立之初,就要从业务视角对集群做好物理资源隔离,将影响范围最小化。
我们将 Doris 集群创建、扩容、缩容等流程拆解,主要操作包含两部分,一部分是内部的基础设施平台,一部分是 Doris Manager。整个流程其实是很长的,如果不做运维流程整合,单纯靠人肉做运维,是很难的,并且极容易因为操作失误导致线上故障。我们有着高频的运维操作,各种大促,都需要频繁的操作集群。并且我们还要面对全球多地域集群的运维部署。
为了让整个自动化运维的开发工作降低,通过对整个运维流程的拆解,得益于内部基础设施和 Doris Manager 能力完善,我们将环节中可以复用且独立的节点全部抽成一个个最小的原子能力,将原子能力全部融合到 Doris 运维平台中,然后按照 workflow 的方式去编排所有核心流程,比如:创建集群只需要选择集群地域,规格,即可 10 分钟完成集群初始化交付业务侧使用。而针对大集群的资源组隔离,我们也做了深度融合,支持快速新增资源组,并且 By 资源组做批量扩缩容(针对不同的业务容量需求,扩缩容更加精细化)。在全球化部署上,也不需要多地域系统来回操作,全部收口到一个系统中。
BadSQL 可以说是 OLAP 数据库最痛的点,尤其在报表的取数场景上,很多大查询,BadSQL 较多,极易影响集群稳定性。想事前完全隔绝掉 BadSQL 是几乎不可能的,所以事中事后的工作也很重要。针对大查询的场景,尤其临近大促前新上的一些场景,我们都会做流量打标,打标的目的有助于我们快速定位到 SQL 的来源和使用场景,也防止人员更替,后来者对实际 SQL 的使用场景不熟,出现问题后,无法做出快速决策。而另一方面,Doris 的审计日志是我们的重要分析手段,我们可以基于 cpu 耗时、内存使用量、扫描行数、扫描字节数等不同维度分析大查询,还可以基于用户级别的查询统计分析等,进而快速找到实际的 BadSQL Detail。
除了常态化的 BadSQL 治理,在紧急情况下的 Bad SQL 应急处置措施也很重要(这里主要指的是报表类的分析场景,应用侧的数据产品基本有数据服务收口,管控较严,BadSQL 基本没有),这里我们有两种较为常用的方式:
为什么我们要做配置化的数据清理工具,因为分区表 TTL 无法满足,业务侧的历史数据清理逻辑较为复杂,不是简单的按分区清理就能解决,如果不做这个能力的支撑和收口,业务侧在没有 Doris 知识背景的前提下,会直接执行 delete 大批量删除,我们知道 delete 操作在 Doris 里是一个很重的操作,会影响集群的稳定性。数据清理工具上我们支持了用户自定义删除逻辑、每批删除条数、删除操作可执行时间段、执行间隔等等配置项,而在删除方式上,我们选择了基于导入的标记删除方式,相比 delete 方式,性能会提升很多,并且对线上的查询性能影响可忽略不计。
Doris 的资源组隔离是一个很 nice 的能力,所以在大集群物理结构设计时,我们高度结合的 resource tag 能力。比如针对仓储业务的集群,内部的业务会分订单、出入库、补货、库存、发运等等。站在业务的视角将独立的业务拆分,每个对应的一个 DB,都有自己独立的账号(应急处置时,可以 By 账号做限流),并且每个 DB 都是独立的资源组,在 BE 层面是完全物理隔离的。
而针对有跨业务之间的关联查询,我们上层使用逻辑视图来建立关系,针对跨业务的逻辑,比如订单域的表需要被出入库使用,我们没有在做资源组上的拆分,在设计之初我们也想过一个表在多个资源组下,但考虑逻辑结构设计上过于复杂,虽然能够隔离的更彻底,但不利于我们以后的维护,所以选择了现在看到的折中方案,已经能够最大程度的保证业务之间的相对独立,互相影响做到最低。
合理的使用规范一定是保障集群稳定性的重要手段,有些规范我们可以基于产品能力做收敛,有些规范要靠文档的方式给大家做宣导,这是一个长期逐步培养的过程。尤其是使用 Doris 的第一步就是建表,我们对建表有着严格的要求,表建的好不好直接影响查询和写入的效率,甚至是集群的稳定性。表格中我们列举了一些比较典型代表性的使用规范,这些规范的背后很多都是使用中犯过的错误,导致集群出现抖动的根因。
OLAP 压测可能是一个比较小众的词,很多时候大家是在做选型的时候做个性能测试对比,而实际面向大促的时候,结合整个集群的所有业务场景的促前压测是很复杂的,OLAP 数据库压测的复杂性,它跟传统 TP 数据库压测有着本质的区别,所以每年大促在压测上我们也是花的时间最多的。
整个压测的流程,压测样本准备和压测模型的评估是相对耗时的部分:
第一步:我们会基于历史查询的 SQL Pattern 做聚类,将 SQL Pattern 的数量收敛降低。
第二步:针对聚类后 SQL Pattern 会做特征的提取,这里会结合业务侧明确提供的关键词/打标标记,建立关联关系。
第三步:结合血缘,建立实际压测场景和特征的关系,压测场景实际就代表一个明确的数据查询场景,是一个接口、报表等。
第四步:压测场景明确后,用户要基于压测场景评估 QPS、偏移量等。
第五步:线上 SQL 采集,基于特征随机采样,当然这里也会考虑到一些 SQL Pattern 查询权重。
第六步:采集到 SQL 会做偏移量的 SQL 改写,因为大促单量同比日常会翻几倍,比如这个 SQL 日常扫描 10 天的数据只有 100 万,但实际大促期间 10 天的数据是 1000 万,所以要通过对日期的偏移,模拟大促的数据规模。
第七步:By 压测场景的 QPS 进行全局压测。
第八步:压测结果复盘,目标 QPS 和实际 QPS 是否满足预期,观察集群的各项指标是否满足预期。
注:这里只讲解了查询压测流程,写入压测没有展开讲(写入压测相比查询会容易),实际压测的时候,是查询和写入一起压测。
整个监控的核心策略,全局视角紧盯大盘核心指标(主要聚焦在大促高峰段),日常视角关注集群告警,配合每个集群的不同维度的指标信息,基本能够事半功倍。我们将问题总结为三类,也是日常运维我们使用较为高频的:
后续规划,我们会聚焦四个点:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。