摘要:本文整理自聚水潭数据专家张成玉,聚水潭高级数据工程师应圣楚,在 FFA 2022 行业案例专场的分享。本篇内容主要分为四个部分:
实时数仓的建设和发展
数据中台的产品体系及架构
实时计算的实践和优化
对实时计算的未来展望
Tips:点击「阅读原文」查看原文视频&演讲 ppt
聚水潭是一家做电商 ERP 的公司,ERP 主要由四个模块组成,OMS、WMS、SCM、DRM,其中 OMS 是订单管理系统。从 2014 年发展至今,聚水潭已经对接了 300+线上平台渠道,客户通过我们的 ERP 产品可以统一做订单的管理,避免了需要去各个线上平台单独处理,全渠道也是由此而来。基于 ERP 的底座,我们的数据团队打造了为商家服务的实时数据中台,目前已经有两万+商家付费订阅。
01
实时数仓的建设和发展
聚水潭发展至今大概经历了四个阶段。
第一阶段,为了满足商家报表的看数需求,提供了 SqlServer 的在线查询。但它有一些弊端:
无法提供丰富统计指标;
业务库耦合,RT 不稳定,商家体验差。
分库分表很难全局聚合统计,影响运营分析。
第二阶段,通过 AnalyticDB、多集群 ETL 做 T+1 的离线分析,补足 SqlServer AP 能力的不足。
第三阶段,通过 Flink+MC 实现实时/离线 Lambda 架构的双链路,MC 补齐了模型、调度、跨集群统计的短板。计算引擎实现了秒级更新,支持业务高时效的统计需求。
第四阶段,实时数仓 1.0 落地,通过 Flink 实时模型规范、数仓分层落地,包括自建 DB 提供实时维表和外置状态存储,用 Hologres/PolarDB 作为 ADS 层存储,提供不同场景高效查询。
上图是我们实时数仓的架构。我们大多数的数据都在 SqlServer 的业务库,然后通过我们自研的同步中间件,同步数据到 Kafka 或者 SLS 里,作为 Flink 的 ODS 层。接着通过 Flink 清洗到 DWD 层,DWD 层和我们自建 DB 做了很多维表关联,包括外置状态交互。接着通过 Flink 做 ADS 层的聚合运算,ADS 的结果根据不同的业务场景落到不同的存储引擎里。
目前在聚水潭主要分为两个模块。第一个是在线服务,它目前支撑我们的实时数据门户、实时大屏的业务场景,主要由 PolarDB 和 Redis 承接。第二个是 AD-HOC 分析,它目前支撑实时物流场景,主要由 Hologres 和 AnalyticDB 承接。
02
数据中台的产品体系及架构
聚水潭的数据中台主要为商家服务,基于商家的看数场景,我们抽象了三个核心要素,分别是角色、数据、场景。简而言之,就是什么样的人,在什么样的场景,看什么样的数据。
下面通过两个场景,带大家感受一下,为什么我们要通过实时计算的方式来满足商家高时效的看数需求。
场景 1:在线交易实时多维分析。商家运营人员经常要面对在线交易实时多维分析的场景。最开始我们通过在线库提供简单的支持,但在线库有大商家 RT 响应慢,多表关联性能差,AP 查询性能差的问题。所以我们基于实时计算,在中间层做多表关联,在应用层实时聚合,将数据量级降低。通过 KV 做快速查询,来满足商家高时效的快速场景。
场景 2:仓管发货实时跟踪。我们的商家很多都有自己的仓库或者三方仓库,对于仓库内的仓管,他们需要对每天的发货情况做实时跟踪。最开始我们通过离线计算的方式产出 T+1 的数据,但这就会导致今日发货进度无法感知,发货不及时产生资损,所以商家有很强烈的实时看数需求。我们通过实时计算保证数据的秒击产出,且我们提供了多个仓库发货进度的实时统计,仓管可以基于我们的实时分析数据来做实时驱动,调配发货。
上图是我们实时数据中台的完整架构图。目前最底层的数据源已经对接了 300+平台,100+物流公司,通过实时计算的分层来支撑多业务场景、多主题的数据分析。目前我们的实时场景可以分为两部分,实时场景分析和实时风控监控。
实时场景分析可以分全渠道今日销量统计、多平台多店铺汇总统计、重点商品多维统计、多平台直播分析、售后类型实时分析、发货进度实时跟踪。
实时风控监控目前做的比较多的是物流实时预警,未来将要做的库存实时监控、价格实时预警。
商家的业务同学可以大致分为运营同学、售后同学、直播同学、仓库同学。他们在我们的实时门户里都能找到自己对应的业务场景,满足他们实时看数的需求。大致我们分为了以下六个板块。
1. 多平台多店铺汇总指标,实时趋势历史对比。
2. 重点店铺核心渠道置顶,新店铺新渠道孵化。
3. 主推款式重点商品关注,新款新品销售跟踪。
4. 发货进度及未发货情况,关键节点超时风险。
5. 主播带货支持跨天统计,头部主播直播爆品。
6. 售后订单退货金额统计,售后单据原因跟踪。
以上板块可以满足不同的业务同学,其中“多平台多店铺汇总指标、重点店铺核心渠道置顶、主推款式重点商品关注”可以帮助运营同学快速响应。“发货进度即及发货情况”可以帮助仓库同学做发货的实时跟踪。“主播带货支持跨天统计”可以帮助主播做跨店统计。“售后订单退货金额统计”可以帮助售后同学做售后订单的实时跟踪。
我们的全渠道实时数据大屏主要满足商家平时或者大促阶段的投放诉求。不但涵盖了实时数据中台的大部分模块,又做了销量热力地图,让分布一目了然。
03
实时计算的实践和优化
我们把 Flink 的一些难题归纳为以下三类。
1. 多流关联。这里特指多事实流状态关联,关联周期长。
2. 大状态管理。它可能会有 TB 级的状态,甚至更大,且它的 TTL 可能会超过一个月。
3. 高时效体验。包括稳定性、任务延迟的概念。
举个例子,商品分摊、拆分是 Flink 的一个任务,它属于数仓的公共层。这个任务背景是客户想要看到商品粒度金额、件数、成本价等等信息。对于这样的需求,我们把整个流程拆成三步。
1. 三流关联。三流分别是订单流、订单明细流、操作日志流。订单流里是支付时间等基本的订单信息;明细流里是商品粒度的成本价等信息;操作日志流会记录一些删除的信息、update、更改其他字段的信息。关联之后的数据,我们再根据业务逻辑做商品分摊。
2. 商品分摊。这一步我们会把订单上的金额,分摊到具体的每个商品上。这样我们就可以得到商品的金额和件数了。
3. 组合装拆分。它有个特殊的业务场景,商家会把不同的商品打包成另外的商品来卖。比如 a 和 b 商品,会打包成 c。如果发生 c 的订单,需要拆分成 a 和 b 做统计,具体去看它的成本价和销售金额。
在上面的场景中,有一个多事实流关联的问题。最初我们是用 Join 来解决的,也就是把三条流分为两次 Join 去解决,但任务效率不太理想,状态也较大。之后我们参考了一些行业案例,并了解到 UNION ALL+KEY BY 是关联键一致的,所以后来我们用 UNION ALL+KEY BY 替代了多次 Join。这个方案的原理是我们可以复用它的状态,即 UNION ALL+KEY BY 每条流的状态只保留一份,而 Join 保留多份。
另外,多事实流关联还有一个关联周期长的问题。在某些场景下,比如订单今日发货了,而明细表却是一个月前的,这时它的状态保留时间不确定,甚至可能超过了一个月。对此,我们会引入额外的状态管理机制。
在分享状态管理机制前,先来阐述一下 Flink 对一些大状态的痛点。
1. 效率。效率问题在小状态的时候是没有问题的,效率很快,但当状态达到 TB 级别,甚至几十 TB,它的读写效率就会显著下降,且状态恢复任务的时间也比较长,通常需要几十分钟的时间。
2. 稳定性。Flink 的状态越大,Checkpoint 的时间越长,这就会导致一些延迟的波动,也就会不满足我们对于高时效的要求。
3. 灵活性。目前社区版 Flink 和商业版 Flink 都只提供了 TTL 这个清理策略,所以我们无法根据业务的一些特性,定制删除这个状态。
基于以上痛点,我们提出了状态外置+冷热分离的方案。对于大状态的业务场景,我们会把状态完全外置到 KV 数据库里,然后把 StateBackend 作为外置数据库的缓存。在缓存里 Flink 算子与数据交互,优先读取 StateBackend 的数据,当流式读取读不到的时候,才会走到外置的冷数据层,也就是外置的 KV 数据库。这样我们就可以尽量减少的访问外部的数据库了。
写入的过程也是 StateBackend 流式写入,但写入冷数据层是 Batch 写入。它虽然不能保证 StateBackend 和 KV 数据库的状态一致性,但我们的业务场景是 AtleastOnce 语义,可以在代码里判断它的业务逻辑,通过业务逻辑规避数据重复。
通过这个框架我们可以实现以下优势。
1. 可以支持更大 TB 级的大状态。大状态的大小取决于外置数据库的存储大小。
2. 月周期级别的 TTL。这个 TTL 可以非常长,可能超过一个月,但它的效率比较高,因为 80%的数据都走到了缓存层。
3. 状态可以查询。比如你可以清晰的定位状态的流转变化,通过 SQL 语句查询当前的状态。另外,我们也可以容忍状态丢失风险,比如 StateBackend 由于版本升级或者其他原因,它的状态消失了,我们可以从 KV 数据库无状态重启。
在实时订阅场景中,我们需要对商家保证比较稳定,且延迟非常低的实时性体验,这就要求我们需要保障任务的稳定性和延迟。在这个任务里,我们的服务包括:
1. 按需计算,即只有开通或者订购的商家才会做计算,这样可以节省成本。
2. 商家开通功能后,需要实时看到数据,这就要求我们的订阅逻辑也需要是实时的。
3. 我们需要保障今日新订阅商家今日指标的完整性,不能从第二天才开始算。
所以,我们做了实时订阅任务,保证任务的稳定性。
热点商家业内俗称数据倾斜。数据倾斜问题我们有两种解法。
第一个优化是订阅流的。我们把本来按照商家粒度聚合的数据打散成商家+订单粒度来聚合。之前视为商家粒度,如果某个商家的数据非常大,它会分发到 TaskManager 下面的某一个 slot,导致 TaskManager 的 CPU 一直拉满。这样它就跑不下去了,延迟也会相应变高。做了打散优化后,可以让所有的 TaskManager 同时触发订阅逻辑,任务的稳定性相对就提高了。
第二个优化,针对分摊任务中有主表和明细表关联的时候,明细表可能出现了几十万条甚至上百万条,主表和明细表关联时的 Key 就会非常大。这时我们把时间窗口划分为 3 秒一个窗口注册定时器,通过定时器触发分摊动作,限制单条订单下最多 3 秒触发一次分摊,有效缓解反压问题。
04
对实时计算的未来展望
对于实时计算未来的展望,我们将围绕流批一体、数据挖掘、风控能力这几个关键词展开。
对于流批一体,我们希望找到能够具体应用 Kappa 架构的场景,提高我们的数据复用性。对于标签体系,当前还没建设比较完整的标签体系,未来会考虑在商家标签或者商品标签方面逐步建设,提高我们内部的运营能力。对于风控能力,我们当前已经有物流预警的风控产品,未来我们将扩展其他的业务场景,比如库存预警、分销价格预警等等,帮助商家解决资损问题。
往期精选
▼ 关注「Apache Flink」,获取更多技术干货 ▼
点击「阅读原文」,查看原文视频&演讲 PPT