作者:杨宏武、王春波首发平台:ApacheDoris
背景
特步集团有限公司是中国领先的体育用品企业之一,主要从事运动鞋、服装及配饰的设计、开发、制造和销售。为了提高特步零售BI主题数据分析的准确性和时效性,降低对SAPHANA平台的依赖,年11月特步集团首次引入了ApacheDoris进行数据仓库搭建试点。在经历实时日报(移动端)和《特步全网零售战绩》大屏两个小项目的成功后,于年月开始逐步启动特步儿童BI、特步电商BI、双十一大屏、特步新品牌BI等多个项目,经过一年的努力,初步完成了基于ApacheDoris的零售数据仓库搭建和上线运行。
在这些项目实践过程中,我们遇到了很多困难,也解决了很多问题,在这里总结出来分享给大家。
总体架构
在特步零售数据仓库的项目中,我们大胆的抛弃了传统的Hive离线数据处理模式,一步从SAPHANA进化到基于MPP架构的单一大数据平台架构。项目基于ApacheDoris集群完成接口数据的接入、仓库层的建模和加工、集市层的建模以及BI报表的即时查询。
先展开说明一下这样设计的原因。在前期的项目经历中,我们既有过基于Hive+Greenplum搭建卡宾零售BI项目的经验,也有基于Greenplum+MySQL搭建斐乐BI项目的经验,还有基于Hive+Doris的安踏户外BI项目经验,得到的结论有:①MPP架构开发效率高,查询和跑批速度远高于Hive数仓;②MPP架构支持有限的Delete和Update,开发的灵活度更高;③项目交付两套环境,运维难度很大;④Doris在架构设计上比Greenplum更为领先,对OLAP支持更好,查询性能也更高。基于以上原因,加上Hive数据处理和查询的时效性无法满足业务需求,所以我们坚定的选择选择了ApacheDoris作为特步零售数据仓库的唯一大数据平台。
确定项目选型以后,我们讨论了数据仓库的分层设计。项目最先启动的是特步儿童BI项目,考虑到系统业务数据存在多个来源,复杂的业务指标口径以及来源相同的不同品牌需要进行拆分,我们在数据仓库层采用了DWD、DWB、DWS三层加工。图1-特步儿童BI项目系统分层
数据仓库分层逻辑如下:
DWD模型层:关联维度数据的加工和明细数据的简单整理,包括头行表结构的合并、商品拆箱处理、命名统一、数据粒度统一等。DWD层的销售、库存明细数据均按照系统加工,每个系统的加工逻辑创建一张视图,结果对应一张物理表。DWD层大部分采用DuplicateKey模型,部分能明确主键的采用UniqueKey模型。
DWB基础层:保留共性维度,汇总数据到业务日期、店铺、分公司、SKC粒度。销售模块DWB层合并了不同系统来源的电商数据、线下销售数据、库存明细数据,还关联了维度信息,增加数据过滤条件,加工了分公司维度,确保DWS层可以直接使用。DWB层较多采用DuplicateKey模型,便于按照Key删除数据,也有部分采用AggregateKey模型。
DWS汇总层:将DWB层加工结果宽表化,并按照业务需求,加工本日、本月、本周、本年、昨日、上月、上周、上年及每个标签对应的同期数据。DWS层较多采用DuplicateKey模型,也有部分采用AggregateKey模型。DWS层完成了指标的汇总和维度的拓展,为报表提供了统一的数据来源。
ETL实践
本次项目采用了自研的一站式DataOps大数据管理平台,完成系统数据的抽取、加载和转换,以及定时任务的执行等。在数据分层标准之下,关于ETL实践,我们主要完成了一些内容:
01批量数据导入
批量数据导入我们采用的是目前最主流的开源组件DataX。自研的DataOps大数据管理平台在开源DataX的基础上做了很多封装,我们只需要创建数据同步任务,选择数据来源和数据目标表,即可自动生成字段映射和DataX规范的Json配置文件。
图2-启数道平台在项目初期,Doris未发布DataX插件,仅通过原始的JDBC插入数据达不到性能要求。产品团队开发了DataX加速功能,先将对应数据抽取到本地文件,然后通过StreamLoad方式加载入库,可以极大的提升数据抽取速度。数据读取到本地文件取决于网络宽带和本地读写性能,数据加载达到了千万数据12.2G仅需5分钟的效果。图-DataX加速此外,DataX数据同步还支持读取自定义SQL的方式,通过自定义SQL可以处理SQLSERVER这种数据库比较难解决的字符转换问题和偶尔出现的乱码字符问题。
批量数据同步还支持增量模式,通过抽取最近7天的数据,配合Doris的主键模型,可以轻松解决大部分业务场景下的增量数据抽取。
02实时数据接入
在实时数据接入方面,由于接入的实时数据都来自于阿里云的DRDS,所以我们采用的是Canal+Kafka+RoutineLoad模式。详细的配置就不展开了,环境搭建完成以后,只需要取Canal里面配置拦截策略,将表对应的流数据映射成KafkaTopic,然后去Doris创建RoutineLoad就OK了,这里举一个RoutineLoad的案例。
0数据加工
本次项目的数据加工我们是通过Doris提供的视图来完成的。利用Doris优秀的索引能力,加上完善的SQL语法支持,即使再复杂的逻辑,也可以通过视图来实现。用视图加工数据,减少了代码发布的流程,避免了编译错误的问题比Hive的脚本式开发更加高效。在完成模型设计以后,我们会确定模型表的命名、Key类型等信息。完成表的创建以后,我们会创建表名+"_v"的视图,用于处理该表数据的逻辑加工。在大多数情况下,我们都是先清空目标表,然后从视图读取数据写入目标表的,所以我们的调度任务都比较简单,例如:
对于数据量特别大的读写任务,则需要分步写入。例如:
当然,视图开发的模式也是有一定的弊端的,比如不能做版本管理,也不便于备份。为此,我们承受了一次惨痛教训,在项目测试阶段,有同事在dbwaver客户端误操作Drop掉了xtep_dw数据库,导致我们花费了-4天时间才恢复程序。因此我们紧急开发了Python备份程序:
然后配合Linux的Crontab定时任务,每天三次备份代码。
04BI查询
本次项目采用的前端工具是某国产BI软件和定制化开发的E-Charts大屏。该BI软件是基于数据集为中心去构建报表,并且支持灵活的数据权限管理。大多数据情况下我们基于SQL查询创建数据集,可以有效过滤数据。本次项目基于该BI平台构建了PC端报表(通过App适配手机也可以直接访问),并且新增了自助分析报表,同步开发了几张E-Charts大屏,实现大屏、中屏、小屏的统一。
数据查询对Doris来说是很Easy的了,基本上建好表以后设置好索引,利用好Bitmap,性能就不会差。这里需要说明的上,在性能压力不大的情况下合理使用视图来关联多个结果集,可以减少跑批的任务和数据处理层级,有利于报表数据的快速刷新。在这方面,我们也是尽可能减少DWS和ADS层的聚合模型,减少大数据量的读写,尽可能复用代码逻辑和模型表,减少跑批时间加强系统稳定性。
实时需求响应
在实时的需求方面,我们分别尝试了Lambda架构和Kappa架构,最后走出来项目特色的第三条线路——相同的视图逻辑,用不同的调度任务刷新不同范围的数据,实现流批代码复用。
项目早期,我们是按照Lambda架构构建的任务,系统数据分为批处理和流处理两条线路,随着批处理的稳定,流处理数据的不准确性就逐步暴露。究其原因,业务系统存在数据物理删除和更新的情况,双流Join之后的数据准确性得不到保障。再有就是同时维护两套代码,实时逻辑的更新滞后,变更逻辑的代价也比较大。
项目后期,基于业务要求我们也尝试了把所有的零售逻辑搬迁到流处理平台,以实现流批一体,但是发现无法处理报表上常规要求本同期对比、维度数据变更和复杂条件过滤,导致搬迁工作半途而废。
最后我们结合项目的实际情况,采用批处理和微批处理结合的方式,一套代码,两种跑批模式。T+1的链路执行最近6个月或者全量数据的刷新,微批处理流程刷新当日数据或者本周数据,实现数据的快速迭代更新。以DWB层为例:
而DWS和ADS层的情况更为复杂,由于跑批频率太高,为了避免出现用户查看报表时刚好数据被删除的情况,我们采用分区替换的方式来实现数据的无缝切换。
弱弱的说一下,Doris的分区替换还需要再完善一下,希望可以支持类似于ClickHouse的语法,即:ALTERTABLEtable2REPLACEPARTITIONpartition_exprFROMtable1;
同时,由于我们设计了良好的分层架构,对于实时性要求特别高的数据,例如双十一大屏,我们可以直接从ODS层汇总数据到报表层,可以实现秒级的实时查询;对于实时性较高的业务,例如移动端实时日报,我们从DWD或者DWB往上汇总数据,可以实现分钟级的实时;对于普通的自助分析或者固定报表,则按照灵活的频率更新数据,兼顾了二者的时效性和准确性。
其他经验
在项目过程中,我们还遇到一些其它问题,这里简单总结一下。01DorisBE内存溢出查询任务耗用的内存过大,导致DorisBE挂掉的情况,我们也出现过。我们采取的方法是所有表都创建副本,然后给Doris进程配置Supervisord自启动进程,失败的任务通过调度平台的重试功能,一般都可以在次重试机会以内跑过。
02SQL任务超时
批处理过程中确实会有一些复杂的任务或者写入数据太多的任务会超时,除了调大timeout参数(目前设置为10分钟)以外,我们还把任务做了切分。前面的调度任务案例已经可以看到,有些写入的SQL我们是按照分区字段或者日期区间来分批计算和写入的。
0删除语句不支持表达式
删除语句不支持表达式,我认为是Doris后续需要优化的一个功能点。在Doris无法实现的情况下,我们通过改造调度平台的参数功能,先计算好参数值,然后传入变量的方式实现了动态条件删除数据。前文的调度任务代码也有案例。
04Drop表闪回
误删除重要的表是数据仓库开发过程中比较常见的情况,表结构我们可以通过Python做好备份,但是表数据实在没有更好的办法。这里Doris提供了一个很好的功能——Recover功能,推荐给大家。误删除的表在1天以内可以支持闪回。
结束语
目前ApacheDoris在特步集团的应用已经得到了用户的认可,今年2月底又对Doris集群进行了硬件升级,接下来会基于现有的接口数据拓展到特步品牌BI应用,并且迁移更多的HANA数仓应用到Doris平台。随着应用的深入,我们需要加强对Doris集群、RoutineLoad和Flink任务的监控,及时发出异常预警,缩短故障恢复时间。同时,随着向量化引擎的逐步成熟和查询优化器的进一步完善,我们需要调整一些SQL写法,降低批处理对系统资源的占用,让集群更好的同时服务批处理和查询需求。当然,也期待社区在资源隔离方面可以有更进一步的完善。
最后提一个重要的产品优化方向,希望社区予以考虑:为了可以更好的用Doris替代Hive数仓,希望社区可以考虑开发存储过程功能。
最后,感谢ApacheDoris社区给予的支持,也感谢百度开源了这么优秀的产品!同时要感谢信息部领导林总和曾经理给予的大力支持与包容。祝愿ApacheDoris社区发展越来越好!