网上药店
您现在的位置: 总经理 >> 总经理权限 >> 正文 >> 正文

菜鸟供应链实时数仓的架构演进及应用场景

来源:总经理 时间:2021/8/22

摘要:在FlinkForwardAsia大会实时数仓专场中,菜鸟数据规划部高级数据技术专家贾元乔从数据模型、数据计算、数据服务等几个方面介绍了菜鸟供应链数据团队在实时数据技术架构上的演进,以及在供应链场景中典型的实时应用场景和Flink的实现方案。

重要:点击文末「阅读原文」可查看FlinkForwardAsia大会视频。首先从三个方面简要介绍一下菜鸟早在年采用的实时数据技术架构:数据模型、实时计算和数据服务。

数据模型。菜鸟最初使用的是需求驱动的、纵向烟囱式的开发模式,计算成本高且完全没有复用的可能性,同时也会导致数据一致性的问题;整个数据模型没有分层,业务线内部模型层次混乱,使得数据使用成本特别高。

实时计算。该部分使用的是阿里的JStorm和SparkStreaming,大多数情况下,二者可以满足实时计算的需求,但是对于有些复杂的功能,如物流和供应链场景,实现起来不够简单,开发成本较高;同时很难兼顾功能、性能、稳定性以及快速的故障恢复能力。

数据服务。数据主要存储在Hbase、MySQL和ADB等不同类型的数据库中,然而对于很多运营人员来说,查询数据库的频率并不高,但使用数据库的成本较高,尤其针对一些NoSQL的数据库;也存在数据使用不可控,如热点阻断、权限控制以及全链路监控等问题。

针对以上问题,菜鸟在年对数据技术架构进行了一次比较大的升级改造,以下将详细介绍。

数据模型升级

数据模型的升级主要是模型分层,充分复用公共中间层模型。之前的模式是从数据源TT(如Kafka)中抽取数据并进行加工,产生一层式的表结构。新版本的数据模型进行了分层:

第一层是数据采集,支持多种数据库中的数据采集,同时将采集到的数据放入消息中间件中;

第二层是事实明细层,基于TT的实时消息产生事实明细表,然后再写入TT的消息中间件中,通过发布订阅的方式汇总到第三、四层,分别是轻度汇总层和高度汇总层。

第三层轻度汇总层适合数据维度、指标信息比较多的情况,如大促统计分析的场景,该层的数据一般存入阿里自研的ADB数据库中,用户可以根据自己的需求筛选出目标指标进行聚合;

而第四层高度汇总层则沉淀了一些公共粒度的指标,并将其写入Hbase中,支持大屏的实时数据显示场景,如媒体大屏、物流大屏等。

原本采用的开发模式各个业务线独立开发,不同业务线之间不考虑共性的问题,但物流场景中,很多功能需求其实是类似的,这样往往会造成资源的浪费,针对该问题进行的改造首先是抽象出横向的公共数据中间层(左侧蓝色),然后各个业务线在此基础上分流自己的业务数据中间层(右侧黄色)。前面介绍的业务线分流由预置的公共分流任务来实现,即将原来下游做的分流作业,全部转移到上游的一个公共分流作业来完成,充分复用公共预置分流模型,大大节省计算资源。下面介绍一个数据模型升级的具体案例—菜鸟供应链实时数据模型。

下图左侧是前面介绍的公共数据中间层,包括整个菜鸟横向的物流订单、大盘物流详情和公共粒度的一些数据,在此基础上菜鸟实现了预置公共分流,从物流订单、物流详情中拆分出个性化业务线的公共数据中间层,包括国内供应链、进口供应链以及出口供应链等。

基于已经分流出来的公共逻辑,再加上业务线个性化TT的消息,产出各业务线的业务数据中间层。

以进口供应链为例,其可能从公共业务线中分流出物流订单和物流详情,但是海关信息、干线信息等都在自己的业务线进口供应链的TT中,基于这些信息会产生该业务线的业务数据中间层。

借助前面所述的设计理念,再加上实时的模型设计规范和实时的开发规范,大大提升了数据模型的易用性。

计算引擎升级

菜鸟最初的计算引擎采用的是阿里内部研发的JStorm和SparkStreaming,可以满足大多数场景的需求,但针对一些复杂的场景,如供应链、物流等,会存在一些问题。因此,菜鸟在年全面升级为基于Flink的实时计算引擎。当时选择Flink的主要原因是:

Flink提供的很多功能非常适用于解决供应链场景下的需求,菜鸟内部提炼了一套Flink的SQL语法,简单易用且标准化,大大提升了开发效率。

此外,Flink内置的基于state的Retraction的机制可以很好地支持供应链场景下的取消订单、换配需求的实现;

后来推出的CEP功能使得物流、供应链中实时超时统计需求的实现变得更加简单;

AutoScaling等自动优化的方案可以使得菜鸟省去了一些资源配置等方面的复杂性和成本;

半智能功能如批流混合等也较好地满足菜鸟业务的实际需求。

下面介绍三个与计算引擎升级相关的案例。

案例1:基于state的Retraction

下图左侧是一个物流订单表,包含了四列数据,即物流订单号、创建时间、是否取消和计划配送公司。假设有一个需求是统计某个配送公司计划履行的有效单量是多少,该需求看起来简单,实际实现过程中有有一些问题需要注意。

一个问题是针对表中LP3订单,在开始的时候是有效的(18分的时候“是否取消”应该是N,表写错),然而最后该订单却被取消了(最后一行“是否取消”应该是Y,表写错),这种情况该订单被视为无效订单,统计的时候不应该考虑在内。

另外,配送公司的转变也需要注意,LP1订单在1分钟的时候计划配送公司还是tmsA,而之后计划配送公司变成了tmsB和tmsC,按照离线的计算方式(如Storm或增量)会得出右上角的结果,tmsA、tmsB和tmsC与LP1订单相关的记录都会被统计,事实上tmsA和tmsB都未配送该订单,因此该结果实际上是错误的,正确的结果应该如图右下角表格所示。

针对该场景,Flink内置提供了基于state的Retraction机制,可以帮助轻松实现流式消息的回撤统计。下图展示了Retraction机制的伪代码实现。第一步是利用FlinkSQL内置行数last_value,获取聚合key的最后一条非空的数值,针对上述表中的LP1订单,使用last_value得到的结果是tmsC,是符合预期的结果。需要强调的一点是,左侧使用last_value统计的字段gmt_create、plan_tms、is_cancel,一旦其中的任何一个字段发生变化,都会发生出发Flink的Retraction机制。

案例2:超时统计

物流是菜鸟中比较常见的业务场景,物流业务中经常会有实时超时统计的需求,比如统计仓出库超过六个小时未被揽收的单量。

用到的数据表如下图左侧所示,其中包含日志时间、物流订单号、出库时间和揽收时间。该需求如果在离线的小时表或天表中比较好实现,但是在实时的场景下,其实现面临一定的挑战。

因为如果仓出库后未被揽收,意味着没有新的消息流入,如果没有消息就没有办法进行超时消息的计算。

为了解决该问题,菜鸟从年初就开始了一系列的探索,发现一些消息中间件(如Kafka)和FlinkCEP等本身会提供超时消息下发的功能,引入消息中间件的维护成本比较高,而FlinkCEP的应用会出现回传不准确的问题。

针对上述需求,菜鸟选择了FlinkTimerService来进行实现。具体来讲,菜鸟对Flink底层的ProcessFunction中的ProcessElement函数进行了改写,该函数中,由Flink的state存储原始消息,相同的主键只存一次,一旦endNode已实操,则state消息置为无效,已超时的消息直接下发。此外,重写编写一个OnTimer函数,主要负责在每个超时的时刻读取state消息,然后下发state中仍然有效的消息,基于下游和正常游的关联操作便可以统计出超时消息的单量。使用FlinkTimerService进行超时统计的伪代码实现如下图所示。

首先需要创建执行环境,构造ProcessFunction(访问keyedstate和times);

其次是processElement函数的编写,主要用于告诉state存储什么样的数据,并为每个超时消息注册一个timerService,代码中timingHour存储超时时间,比如前面的提到六小时,

然后启动timerService;

最后是onTimer函数的编写,作用是在超时的时刻读取state的数据,并将超时消息下发。

案例3:从手动优化到智能优化

实时数仓中会经常遇到数据热点和数据清洗的问题。下图左侧展示了数据热点的流程,蓝色部分Map阶段经过Shuffle后,转到红色部分Agg,此时便会出现数据热点。针对该问题,菜鸟最初的解决方案的伪代码实现如下图右侧所示。假设对lg_order-code进行清洗,首先会对其进行hash散列操作,然后针对散列的结果进行二次聚合,这样便可以在一定程度上减轻倾斜度,因为可能会多一个Agg的操作。菜鸟内部目前使用的Flink最新版本提供了解决数据热点问题的智能化特性:

MiniBatch。原来每进来一条数据,就需要去state中查询并写入,该功能可以将数据进行聚合后再写入state或从state中读取,从而减轻对state的查询压力。

LocalGlobal。类似于Hive中Map阶段的聚合,通过该参数可以实现数据读取阶段的聚合,轻松应对count热点。

PartialFinal。面对更复杂的场景,比如count_distinct的热点,使用该参数可以轻松应对,实现两次聚合,类似于Hive中的两次Reduce操作。

智能化功能支持的另一个场景是资源配置。在进行实时ETL过程中,首先要定义DDL,然后编写SQL,之后需要进行资源配置。针对资源配置问题,菜鸟之前的方案是对每一个节点进行配置,包括并发量、是否会涉及消息乱序操作、CPU、内存等,一方面配置过程非常复杂,另一方面无法提前预知某些节点的资源消耗量。Flink目前提供了较好的优化方案来解决该问题:

大促场景:该场景下,菜鸟会提前预估该场景下的QPS,会将其配置到作业中并重启。重启后Flink会自动进行压测,测试该QPS每个节点所需要的资源。

日常场景:日常场景的QPS峰值可能远远小于大促场景,此时逐一配置QPS依然会很复杂。为此Flink提供了AutoScaling智能调优的功能,除了可以支持大促场景下提前设置QPS并压测获取所需资源,还可以根据上游下发的QPS的数据自动预估需要的资源。大大简化了资源配置的复杂度,使得开发人员可以更好地

转载请注明:http://www.bujiadicar.com/zjlqx/8697.html