Graph + AI 中国峰会火热报名中,点击探索图分析更多可能! 了解详情
写点什么

伴鱼数仓演进

2021 年 8 月 14 日

伴鱼数仓演进

伴鱼离线数仓建立,与伴鱼的业务一起快速发展,从一条业务线,到多条业务线。在演进的过程中,有很多总结和沉淀的内容。本篇文章主要介绍伴鱼离线数据仓库的发展历史,在发展过程中遇到的各种问题,以及针对问题的解决方案。

业务介绍



首先介绍伴鱼的主要业务线,流量型产品:伴鱼绘本,业务型产品:伴鱼 AI 课,伴鱼少儿英语等十几条业务线:

  • 伴鱼绘本:承担着给其他业务线导流的功能,其核心业务流程是,用户注册 app 为起点,app 内广告访问,app 内听读录绘本功能的使用,以及 VIP 的购买、转化。

  • 伴鱼少儿英语:用户核心链路涉及到的实体多,用户申请试听成为少儿英语用户,先触达到销售,然后分配老师,再完成上课,购买课程,然后分配班主任。

  • AI 课:用户购买体验课成为 AI 课的用户,通过分配到运营,运营转化用户购买正式课。


由于各个业务线有互相交叉的部分,比如:数学业务使用少儿业务的班主任作为销售售卖课程、业务线之间也可以互相引流等。导致实体数据之间的关系复杂度较高。


在伴鱼数据仓库部门主要的工作内容:


  • 各个业务线的产品需求支持。

  • 给算法、分析团队数据特征的加工与提供。

  • 公司指标体系的设计与搭建。

  • 数据仓库的底层建设与维护。

  • 全公司数据的收集与整合。

  • 研发团队数据需求提供。

数仓前世


在伴鱼数仓建设之前,数据部门会给各个业务线提供数据支持,当时的业务需求比较少,内容和形式也相对简单。


当时的做法:


  • 业务开发人员自己写 python 脚本。

  • 直连数据库,查询需要的数据。

  • 基于内存计算结果。

  • 将结果数据写出到对应存储 DB。

  • 开发报表展示页面,提供数据报表,或通过邮件将数据结果发送给业务方。


以上数据支持流程足以应对当时业务不太复杂的伴鱼公司,但是随着公司的发展和业务线的增加,对数据的需求量以及需求复杂度都在增加和提高,以上流程的开发效率就显得捉襟见肘,主要体现在以下问题:


  • 数据无法沉淀:脚本产生的中间结果都是存储内存,数据没有任何沉淀。

  • 脚本维护较为困难:不同开发人员写在不同目录下,文档缺失。

  • 数据稳定性得不到保证:脚本历史数据无沉淀,导致每次计算未必可以保证幂等。

  • 开发效率低:由于数据无沉淀,导致使用任何数据都需要重新开发,同一个数据,每个使用方都需要自己开发逻辑。


为了解决以上问题伴鱼开始构建自己的数据仓库。

数仓建设

数仓 1.0

2019 年 Q3 之前,整体数据情况是:数据体量小,团队人员不足,底层表调整频繁,业务灵活多变,要求响应速度快。建设目标:快速响应需求,以最少的人力支持全公司的业务决策需求。基于当时的背景和目标,数仓架构主要是基于 TIBD 构建的 3 层数仓结构,原始数据层、base 层、stat 层。数据整体架构如下图:



数据层级浅,针对主题只抽象出一个层级,保证底层数据可复用即可。其中数据源,出现了日志进入到 hive 的步骤是因为:


  • 数仓基于 TIDB 构建,所有数据都需要同步至 TIDB。

  • 业务形态导致,早期的流量数据不作为重点关注内容,日志数据主要在 hive 中存储,需要使用的数据同步至 TIDB。


随着业务的发展,数据量的增多,业务形态越发复杂。基于 TIDB 构建的数仓已经无法满足要求,主要体现在:


  • 数据口径难以保持一致,虽然基于原始数据构建了 base 层,但是在数据开发的过程中为了满足特殊的需求也经常直接使用原始数据。

  • 日志数据使用日益增多,导致计算能力无法达到要求。

  • 数据库报警频繁,维护成本过高。

  • 当时的 TIDB 版本不支持窗口函数,自定义函数等功能。

  • 难以配合大数据生态体系工具。

数仓 2.0

针对上述问题,从以下几个方面进行了调整:


  • 明确职责划分。

  • 数仓基础平台由 TIDB 更换为 HADOOP 生态体系。

  • 制定数仓建设规范、开发流程。

  • 数仓整体架构的调整,明确新的分层方式,进行更加细化的建模。

职责划分


目前伴鱼数仓团队,承接公司全部业务线的数仓建设工作,对接公司内部各个业务线,每条业务线的形态不同,数据的使用方式也不同。


基于当前能力该如何解决上述问题?调研后发现大体有如下几种方式:


方式一(分总形式):


​业务线或部门自建数仓,各个业务线分别建设自己的数仓,数仓与数仓之间无直接关系,使用其他业务线数据,通过权限申请拉取使用,或通过 FTP 文件的形式同步数据。例如运营商各个省份的数仓是独自建设的,可能由不同的厂商承接建设,在建设后以统一的格式推送至总部,再在总部进行进一步的数据清洗。


方式二(分层形式):


​ 划分基础数仓与应用数仓,基础数仓通过自下而上,面向于主题的方式进行设计,更加专注的做好底层建设。应用数仓通过自上而下,面向于应用的进行开发,更好的支持业务需求。很多大厂当前都是以这样的方式设计,集团总部负责总部的开发与设计,业务线使用总部加工的数据宽表或事实表进行业务开发,如果遇到新的数据表。需要给基础数仓提需求,由基础数仓排期开发。



方式三(总分形式):


​业务线内垂直建设,横向设计,纵向开发,统一设计并制定数仓整体规范,各个业务线按照统一的规范进行各自业务线的开发。跨业务线使用数据需要申请相应的数据权限,了解其表结构与口径,直接使用其他业务线数据。在中小型企业中,业务线杂而多,但是业务线内部也没有数据开发人员,使用这种方式成本较低,并且可以快速响应业务需求。



伴鱼内部也针对以上的部分方式进行思考与尝试:


方式一,自建数仓,这样会带来以下问题:


  • 如果每个团队自己都有一套小的数仓架构,对公司资产来说是资产冗余。

  • 没有一套专业的数据资产对外提供。

  • 每个团队对数仓的认知和理解程度不同,会导致数据无法公用并沉淀。

  • 数据口径、数据质量难以保障。


基于以上问题,数仓是由数据中台统一建设。未对此方式进行尝试。


方式二,分层建设,遇到的问题:


  • 响应及时度达不到业务要求:业务需求要求当天提供数据,如果遇到基础数仓未建模的业务,无法及时提供。

  • 沟通成本高:一个口径不同的研发人员需要反复沟通多次。

  • 不同层级的目标不一致:基础数仓的目标是合理的建设模型,模型排期是以周为单位,应用数仓则是快速响应业务需求。

  • 变动兼容时效性差:业务方对于数据表的调整往往是较为随意的,表有调整或改动基础数仓感知时效性差。

  • 应用数仓自建底层模型:为了快速响应业务需求,应用数仓研发自己开发了所需的 DW 层表,等基础数仓开发完后,无时间进行迁移改造,造成新的烟囱式问题。


方式二最主要的问题是,业务反馈数仓团队效率变低,无法快速响应需求。


方式三,横向设计,纵向开发,遇到的问题:


  • 规范细节统一问题:目前未通过统一的建模工具进行建模,很多新的名词未纳入统一设计的规范中。

  • 跨业务线使用数据 SLA 保障问题:使用其他业务线数据时,如果该表进行调整,可能影响整体调度时间。

  • 部分基础表建设出现重复:类似于烟囱式开发导致的问题,部分小的公共业务表被重复建设。

  • 对人员素质要求较高:需要所有人都可以从数据建模,到上层应用开发都可以高质高效的完成。


方式三最主要的问题是,规范的统一,烟囱式的开发问题。


综上,伴鱼内部确定了当前业务场景下较为合理的职责划分方式,以方式三为主,并进行了部分优化:


  • 公共数据统一建设:用户、设备、公众号、消息等 10+个公用业务数据,统一进行设计与建设,避免烟囱式开发。

  • 然后跨业务线数据关联:由于 DW 层是统一数仓建设层,如果在此层使用了其他业务数据,会导致模型不稳定,会依赖于其他业务线数据的稳定性。增加 DM 层用于跨业务线数据的关联,通过保证 DW 层的数据稳定,达到使用 DW 层数据链路的 SLA。

  • 统一建模工具:数据建模使用统一的工具可以保证公司内全域数据字段的统一。

  • 明确分析师的职责:多条业务线对于分析师的定位不同,边界划分不同。

数仓整体架构



ODS:贴源层,离线或准实时接入的数据,接入多种数据源。


DWD:明细数据层,整合原始数据,有两部分操作:

1)对 ODS 层的数据做一定的清洗和加工,规范化;

2)进行维度建模,对数据表进行单个业务过程的宽表化,冗余维度。


DWS:轻度汇总层,对单个主题的多行为进行宽表化处理(不跨主题)。

DM:数据集市层,对多个主题,跨主题,跨业务线的整合型数据表,面向挖掘,数据分析等。

ADS:应用层,高度汇总数据,面向业务的结果数据。

其中 ODS 层数据源由平台提供数据抽取能力,保证数据的同步,DW、DM、ADS 层统一由数据仓库团队负责。

层级规范


ODS:将各种源的数据接入到 HIVE 中,保留原始数据结构信息。主要数据来源:数据库数据、日志数据、外部数据。


数据库数据:主要两种数据源,一是 MONGODB;二 TIDB,分别通过 oplog 和 binlog 进行同步,可选择以增量或全量的方式进行。


日志数据:通过 Flink 消费 Kafka 中的数据,存储到 HDFS 中。使用较多的是埋点数据,中台统一了 Web 、安卓、Ios 三端的 SDK,保证不同端使用相同的上报形式,并可进行测试,监控来保证埋点的质量。

外部数据:通过统一的清洗,通过工具进行上传,存入 HIVE 表中。


DWD:先规范化数据,再进行维度建模。


对于第一步规范化,很多人认为没有必要,直接划分业务流程,做维度建模就可以完成 dwd 层的建设。思考以下几点:


  • 业务数据表的更换。

  • 业务逻辑变动的兼容。

  • 增量表数据的 merge。

  • 数据字段名称以及类型的一致性。


这些都是数据常见的操作,如果将这些动作与维度建模和合并成一个步骤,建模的物理模型将是混乱的,在伴鱼内部,将此步骤单独构建,产生标准化的表,方便下一步维度建模使用。如:用户级别变化表 ODS 层为增量拉取,DWD 层标准化:增量表 merge ,字段、类型标准化,兼容算法定级,模型定级数据表。保证用户级别变动可从一张表产出。


第二步维度建模,构建思路:


  • 业务建模:梳理业务过程,划分主题。

  • 逻辑建模:确定粒度、确定维度、确定事实。

  • 物理建模:产出单一主题的事实表。


DWS:融合多业务过程,形成对应主题的轻度汇总宽表。构建思路:


  • 确定主题包含的所有业务过程。

  • 丰富业务过程的维度属性。

  • 确定原子指标,建设指标体系。


注意:DWS 表虽然跨业务过程构建,但是不跨主题,保证每个主题下数据的完整性和准确性。

如:交易主体,仅包含与交易有关的业务过程,包括支付、退费等。


DM:面向于业务线、跨主题,构建思路:


  • 梳理业务相关的主题。

  • 确认粒度,构建跨业务的宽表。

  • 冗余其他业务线的相关数据指标。


如:用户行为数据,业务线内从用户注册到用户使用的行为数据汇总,到在其他 app 内的下单,支付等行为数据的冗余。该层面向于对应业务线分析挖掘等,更加方便使用。


ADS:数据应用,按照应用场景进行开发,构建思路:


  • 确认数据开发口径。

  • 确定查询引擎。

  • 产出相应需求。


下图是某业务线在此规范下的整体设计:



未来规划


未来,期望可以真正做到,通过数据赋能业务,驱动业务,更好的体现数据价值,主要体现在以下几方面:


  • 基础能力:保障数据链路的稳定,以及数据的 SLA,通过监控,提前发现异常的调度链路,及时优化。

  • 数据质量:通过数据质量监控体系,保证产出数据的质量,在数据异常波动时可以快速发现问题,定位问题。

  • 数据支持:更好的支持对接的各个业务系统,从而提高整体数据价值。

  • 建模工具:通过统一的建模工具,保证全场景建模,数据产出更加可靠,通过工具使模型的建设更加规范。

  • 指标管理工具:指标体系建设是数据高效使用的第一步,通过指标管理工具管理,原子指标,派生指标。减少沟通成本,保证指标口径。

  • 数据应用:用户画像系统,用户行为分析系统的提供可以简化很多分析工作,提高分析效率,使分析师更好的为分析决策提供支持。

参考资料



作者:彭旭冬

原文:https://tech.ipalfish.com/blog/2021/06/14/datawarehouse_devlopment/

原文:伴鱼数仓演进

来源:伴鱼技术博客

转载:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2021 年 8 月 14 日 08:004751

评论

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

OpenKruise 如何实现 K8s 社区首个规模化镜像预热能力

阿里巴巴云原生

Serverless 容器 云原生 k8s 调度

行业资讯 | Android WebView 致安卓应用闪退,mPaaS 助你规避这波 Bug

蚂蚁集团移动开发平台 mPaaS

android webview mPaaS 离线包 UC内核

活动 | Apache Pulsar Meetup 欢迎报名

有道技术团队

活动

一周信创舆情观察(3.15~3.21)

统小信uos

力扣(LeetCode)刷题,简单题(第13期)

不脱发的程序猿

面试 LeetCode 算法面经 28天挑战 3月日更

2021最新分享三面百度提前批(Java开发岗)面经 已拿Offer

比伯

Java 编程 架构 面试 程序人生

为了跳槽刷完1000道Java面试真题,没想到老板直接给我升职了

云流

Java 程序员 架构 面试

我在阿里实习做开源

阿里巴巴云原生

阿里巴巴 云原生 dubbo 个人提升 中间件

单账户实时记账能力达2万笔每秒 蚂蚁启用新一代高性能记账引擎

DT极客

实现跨生态互联,区块链赋能智能家居新体验

旺链科技

区块链应用 智能家居

程序员去大公司面试,小程序FMP优化实录,已拿offer入职

欢喜学安卓

android 程序员 面试 移动开发

LeetCode题解:92. 反转链表 II,迭代,JavaScript,详细注释

Lee Chen

算法 LeetCode 前端进阶训练营

从解决Github TimeOut到经典面试题:从输入URL到浏览器显示页面发生了什么?

秦怀杂货店

GitHub TCP 网络 HTTP DNS

困扰一周的奇葩bug:重复相似代码多,导致单片机程序跑飞

不脱发的程序猿

28天写作 硬件设计 嵌入式软件 单片机 3月日更

阿里面试官:Android开发真等于废人?已拿offer附真题解析

欢喜学安卓

android 程序员 面试 移动开发

字节抖音iOS客户端实习 123hr面 面经

iOSer

ios 字节跳动 面试 抖音

C 语言性能优化:循环条件i<=n与i!=0的性能差异

1

实习就参与“服务过亿用户的项目”,是什么体验?

阿里巴巴云原生

Go 开发者 云原生 调度 应用服务中间件

有道技术岗大揭秘!这么幸福的生活,真的是熬夜掉发Top1的职业吗?

有道技术团队

招聘

报名倒计时 | 有道技术沙龙,聊聊明星语音背后的故事

有道技术团队

活动

Go Mysql Driver 集成 Seata-Golang 解决分布式事务问题

阿里巴巴云原生

Java Go 微服务 云原生 seata

可能是绝唱!阿里资深工程师深度解读Netty底层核心源码

Java架构追梦

Java 源码 架构 面试 Netty

被MySQL慢日志查询搞废了?3分钟教你快速定位慢查询问题!

驻云DataFlux

云计算

池化技术有多牛?来,告诉你阿里的Druid为啥如此牛逼

互联网架构师小马

透过 3.0 Preview 看 Dubbo 的云原生变革

阿里巴巴云原生

容器 运维 云原生 dubbo 应用服务中间件

python编译器中出现了绿色波浪线,光标放上去出现的提示是什么意思?

Emotion

这个GItHub上的Java项目开源了,2021最全的Java架构面试复习指南

云流

Java 程序员 面试

定义结构体访问结构成员的三种方法

Emotion

Go Storage存储包封装

非晓为骁

Go storage

Flink 执行引擎:流批一体的融合之路

Apache Flink

flink

为什么python中程序的结果会一直输出,需要怎么解决

Emotion

聊一下 Mesh 数据平面 Sidecar 与 Service 通信的那些事儿

聊一下 Mesh 数据平面 Sidecar 与 Service 通信的那些事儿

伴鱼数仓演进-InfoQ