可能是最全的数据仓库全景科普和开发方法论!
点个关注👆跟腾讯工程师学技术
我之前的回答总是零散的,点到哪里就说哪部分的方法,没有一个比较成体系化总结。在重构和新建了几个业务的数仓以后,用文字的方式对数据链路上下游相关环节的理论和工作中的经验加以总结,希望能给大型业务提供数仓标准化ETL的经验,给中小型和初创型业务梳理出常见数仓建设问题,厘清数仓建设的重点,从而进行快速的优化和提效。
那么,就让我们从数据的诞生一步步开始吧。
数据的源头是数据采集和上报。
“看似很小的视频为什么消耗了我那么多流量?数仓使用的数据是否就是业务DB里的数据?”
第一个问题的答案是:在APP启动的过程中,会以很高的频率进行着数据采样和上报。在目前的主流应用中,你所看到的和触摸屏幕产生的操作基本都会被采集几十或者上百个参数后上传到应用开发商的服务器上,这就造成了实际的流量消耗比视频本身的大小要多很多的情况。
这里引出数据采集的本质,是对连续的现实世界的采样,并且以结构化的方式存储起来。这样,应用开发商就能在任意时间,从一条条数据里,恢复出用户在APP里的一整套行为。但因为存在存储成本,原始数据一般不会保留太久,具体的保留时间要根据业务和计算需求来确定。
(一)数据采集
采集内容
What
操作内容。诸如页面、曝光、点击等操作和相关的业务参数在此进行采集。在前端框架技术上支持的情况下,用户操作的来源和去向也可以根据统计需要进行采集。
数据采集和上报是为了优化服务的,不能过度影响到应用的正常功能,所以需要在一定程度上进行权衡与精简。而操作内容的采集场景,存在大量的前后端数据交互,若请求数据结构过大,则可能影响传输性能进而影响使用体验。
采集方式
SDK采集
SDK通过内部集成采集和缓存能力,统一采集时机和采集策略,标准化采集事件来进行全局参数采集,是从数据源头改善数据质量的重要方式,已经被越来越多的大型业务所使用。其优点是标准化程度高,降低前后端开发人员的开发量;缺点是开发这一套工具需要较大的前期投入。
采集时机和采集策略的统一是SDK采集相较于埋点采集的重大改进。用曝光场景举个例子,若使用埋点上报,有些开发人员在目标露出屏幕100个像素时采集,另一些开发人员可能在目标露出5%时进行采集;不同的开发人员在采集同一个参数时,使用的代码和采集路径也不一定完全相同。在大型应用中,数据的采集不是一次就能完成的,而是一个分阶段进行的过程,采集的参数个数也可能不是几个,而是几十上百个,所以不同的采集时机和采集策略就意味着能采集到参数的个数和质量也不尽相同。
(二)数据上报
拿到采集的数据以后,需要进行数据的上报,才能被后续的链路所使用。按采
集地点的差异,数据上报可以分为
客户端(前端)上报
客户端在采集到的数据后,直接或在缓存N条以后,批量将数据通过网络发送到日志服务器。这个过程可能由于网络波动或者用户直接杀掉进程导致部分数据上报缺失;有些应用为应对网络问题会内置上报重试逻辑,一定程度上解决上报缺失的同时也引入了重复上报的可能性。
后台上报
后台服务在用户触发较为关键性的操作时(例如访问、下单、关注等)或者后台主动操作时(例如发券、回收权限等)进行相关参数的采集和上报,也是通过网络发送到日志服务器上。但因为后台服务一般处于比较稳定的内部生产环境,所以上报的成功率会比客户端更高,一些对准确性要求较高的统计数据可以使用后台上报的方式。
BINLOG上报
数据库BINLOG的采集和上报一般是集成在一起的,可以在采集后立即发送到消息队列(多为Kafka队列)完成数据上报。
(三)数据源选择
那么顺势提出另一个问题:“什么时候使用DB里的数据,什么时候使用经过上报和数仓加工后的数据呢?”
不能说这个说法不对,但是我们可以类比一下:一棵大白菜,从农场到家里,不就是摘下来,一个货车运到楼下菜市场,然后买回来就可以了么?可以说,这种方式对于一个小村镇来说,尚且可行,但如果面对的是一个人口2000多万的大型城市,要做到这一点,就不仅仅是看上去那么简单了。
本章节将一步步回答这个问题,讲述如何建造像“城市”一样运转的数仓。
(一)确定建设标准
(二)梳理现存问题
常见数仓问题
公共底层加工逻辑分散:对于来自多个数据源,但需要使用相同过滤和解析方式公共底层数仓,其过滤和解析代码在每个任务或配置中直接静态复制,未做到统一管理。加工逻辑分散带来的影响是如果公共底层数仓字段需要更改(增删,修改过滤、解析方式等),需要刷新一遍所有相关任务的代码。如果还存在着无法感知到所有的修改位置、修改进度不一致、修改过程出现问题等情况,下游的数据使用就可能出现问题。
如图展示了基于公司内部系统,将公共底层加工逻辑从分散(深蓝色动线)到统一(红色动线)的改动实践。
批流建设分离:实时数仓和离线数仓在机制上无法使用相同的清洗和加工逻辑。这是Lambda架构下很常见的问题,可能直接影响到实时数仓和离线数仓的数据一致性。
局部业务问题
除此之外,还有一些个别业务数仓可能存在的问题
数据含义模糊:存在于数仓各个层级的数据中,包括但不限于字段内数据存在多义性(例如使用函数nvl(id1, id2)的结果作为id1)、字段名与含义不符(例如相同的指标名称,在某些表中表示当天的统计量,但在另一些表中表示当年累计的统计量)、维度和指标的组合存在偏差(例如时间字段内的含义是多天的范围,但指标统计的仅仅是当天;或者将不相关的字段,诸如将维度:商品Id和指标:App启动次数组合在一起)等。
数据的多义性会给下游使用带来困难,有时候下游需要确定性的某一种ID,那么就还需要恢复处理,如果判断条件不足还会出现无法分离的情况;字段名含义不符增大了数仓的使用成本,即每一次个字段的使用都要通读上游所有代码才能确定其含义;维度指标偏差则可能产生错误数据,并且给下游使用方带来困扰。
溯源性差:由于数仓加工代码逻辑限制,或者数据表的生命周期设置不合理,造成的历史数据重跑困难,或者历史问题现场无法恢复。数据的重算和问题溯源是常见的数仓需求,如果无法回溯则可能导致错误数据的累积,或者无法很好地帮助业务定位问题。
指标膨胀:由于缺少规范上的约束,导致指标中涵盖了本可以作为维度的内容,造成了指标膨胀。例如使用<0~10岁付款金额、10~15岁付款金额、15~20岁付款金额……>作为多个指标就不如使用维度<年龄段>+指标<付款金额>更简洁高效。随着业务的发展,膨胀过度的指标会导致应用数仓越来越臃肿且难以维护。
数仓规范缺失:数仓开发中缺少统一的规范限制,导致任务设置、元数据管理、数据层级调用、字段命名、计算口径等随着开发野蛮生长,并最终导致开发效率降低。
(三)明确建设步骤
理解业务
开始建设数仓之前,首先要全面了解业务逻辑,这样更便于做出正确的数据域和数仓架构划分。
确定了业务逻辑以后,下一个关键步骤就是抽象业务行为,也就是划分数据域。如果你的业务是内容类,那么曝光(页面、元素)、点击、播放、进入退出应用(如果拥有独立APP)等就是业务内的基本行为;如果你的业务内容是电商类,那么加购物车、下单、支付、发货、退款等就是业务内的基本行为。
不论自身业务的数据源质量如何,数据开发人员的价值体现为无论基于什么上报基础都能构建对下游友好的数仓。但也可以明显看出,如果数据源质量太过恶劣,那势必消耗数据开发人员大量的时间在清洗与规整上,在数仓其他方面的建设不免分身乏术,这时可能就需要考虑数据源治理的事情了。
制定开发规范
一千个读者就有一千个哈姆雷特,每个开发人员的开发习惯也各不相同,所以对于多人协同的数据开发来说,制定统一的开发规范才能保证开发标准不会在内部就乱了套。
遵循建设原则
有三大原则贯穿了数仓建设的始终,我将其总结为一致性、准确性和复用性。
一致性
同理,数仓的命名(表名、维度名和指标名)也需要在全局有一个统一的规范,避免在一个数仓中出现同一个指标,在不同表里叫不同名字的尴尬场面。
准确性
准确性是数仓开发的生命线,对于希望使用数据驱动的业务来说,一份不准确的数据的危害比没有数据还要大。更细地来说,准确性可分为明细层字段的准确性,和聚合层计算逻辑的准确性。
明细层字段的准确性可以通过上报校验或者白名单入数仓来规范,上报校验的结果定期反馈给上报开发方进行修正。白名单过滤掉不合规范的数据,保证数仓内的数据100%可用,但因为更新白名单的成本高,并且会丢弃相当一部分业务数据,很少被正式业务所采用。
聚合层计算逻辑的准确性由于和业务耦合较深,一般通过业务开发间相互的代码CR、产品运营的数据敏感度和测试同学的用例测试来保证其准确性。
复用性
数据分层将数仓各个功能模块解耦,分别满足不同等级的数据需求,是重要的数据加工手段。这里二八定律依然有效,即20%的表可以满足80%的数据需求。根据每一个需求,从流水数据一路开发到应用数据的烟囱式开发是不可取的,因为在业务量扩大后,维护这些数据的统一就会变成一件非常麻烦的事情。
(四)构建数据模型
绝大多数业务,其基础数仓表都可以分为流水表和维表两大类,在此之上可以建立各种类型的聚合表、应用表、模型表等,构成如图所示的大致引用关系。
流水表
根据使用频率,有些流水表需要进行一定的数据过滤来让下游更方便地理解和使用。例如有些数据源中会含有某个数据域内【非成功】或者【已知的明显异常】数据,那么在设计这个数据域的基础数仓表时,直接过滤掉这些数据,就要比把所有数据都落表,再告知下游所有使用方去过滤掉上面2种异常数据要好得多,即谓词下推。这样一来是使用方需要理解的内容更少,二来可以避免不同使用方自行过滤掉不同范围的数据导致的下游某些指标的计算口径不一致的问题。
与之匹配的操作是,适当增加原始层数据的存储时间。这样如果需要对问题数据进行分析时,也可以在不影响基础数仓的情况下单独对原始数据重新解析和分析。
轻度聚合表
轻度聚合表主要实现对相似数据域的指标聚合和口径统一,并且保留部分重要的去重参数以便应用层进行后续计算。
可加和类指标(次数、金额等)从流水层需要经过一些计算逻辑才能变成对应指标,这个口径统一维护在轻度聚合层,不仅下游使用方可以避免理解复杂的计算逻辑,直接使用轻度聚合层加工好的指标,而且在口径需要修改时可以做到无需下游改动,同时生效。
轻度聚合层很明显地体现了数仓建设原则中的一致性和复用性。
维表
维表是对任意一层数据表中信息的关联与拓展,字典表也算一种维表。
流水层和一些聚合层不方便直接展开(比如某个视频的37个属性)的字段,可以维护在维表中,下游在使用的时候进行关联。维表在指定的主键下只有一条行记录,但可以很宽。不建议在相同主键下维护2张及以上的维表(除非有使用频次和效率的考量)。
一般情况下维表需要落地一份存储供下游使用,而不是从原始数据层直接解析后写在关联逻辑里。一方面避免读取上游表全部分区的情况,另一方面使下游维度的使用保持一致。
模型表
基于基础数仓可以根据使用需求构建一系列模型表。以下举两个例子简单描述其使用场景,其他种类的模型表可以举一反三。
用户模型表不仅可以保存性别、年龄、学历等基础信息,也可以附带来源渠道、活跃度、进行某些关键行为的次数、内容消费习惯等业务拓展信息,提供更全面的分析基础。
漏斗模型表可以统计群体用户在某种周期内,每一个步骤的操作。在内容类应用里,可以是用户从进入应用的每一步跳转直到退出的过程;在交易类应用里,可以是从浏览、加购物车、下单、支付直到完成售后的过程。
数据应用
(一)数据加工
(二)数据血缘
数据血缘类似族谱一样,反映数据加工链路上的关联关系。由此我们可以弄清楚一份数据源可以影响到多少下游数据,反之亦然。数据血缘的精确程度可以分为表级别、字段级别和行列级别,可以通过分析执行语句,或解析计算引擎的执行计划来实现。由于业务计算逻辑的复杂性,血缘分析一般由数据平台提供服务。
表级别的数据血缘已经由欧拉 - 腾讯数据资产平台实现。最精细的行列级别数据血缘是数据链路工业化的基础,未来可以实现数据上报、数仓加工、可视化展示全链路的完全拖拽式开发,有可能成为下一代标准数仓开发方式。
(三)数据质量
数据质量包括数据源的质量和数仓质量。
数据源质量
上游数据源的质量直接影响数仓质量的好坏,要求数仓开发团队人为地修改上游数据源的方法既浪费时间(逻辑校对时间和计算时间)又不便维护,最终造成臃肿的数仓逻辑。
数据源质量可以按三级标准进行要求:
有没有:字段是否有上报。
对不对:上报是否符合该字段应有的格式。
准不准:字段的内容是否在业务内具有正确的含义。
三级标准依次递进,假设一个业务的内容id是11位字母+数字的组合,如果一条上报的这个字段符合这种组合方式,但在全部内容维表中都找不到这个id,那么只能说这条上报达到了【对】的要求但达不到【准】。
数仓质量
数仓质量这个命题范围较大,包括了数仓的准确性,及时性,一致性和使用便捷度等等。这里主要讨论两个点:异动监测和数仓复杂度。
如果说对于一个较为平稳的业务关键指标(如DAU,GMV等),在下跌了超过50%的第二天,还没有预警发出,那么就是异动监测没有进行到位。监测数仓数据量和关键指标异动,可以基于数据中台,也可以自行设置定时任务,无论是哪种方式,最终都要通知到开发负责人,及时排查问题并给出处理结论。
(四)数据实验
“使用什么样的引导文案,用户更可能在线上为公益活动进行捐款?”
对于用户群体的实验一般需要几天甚至几周的时间才能得出置信结论,单层实验可以让我们知道上述问题的答案,多层数据实验可以让我们更多地知道其他问题的答案。
单层实验
类似于控制变量法,单层实验将用户依据某种策略分成不同的群组,取其中的部分群组进行两种或三种策略的实验,并设置对照组。
在实际验证开始之前,首先进行空跑期验证,对于实验想要观测的指标,在空跑期内保证各个组之间的差异在可接受的范围之后,进行实际验证。验证结束后通过假设检验,得出是否可以认为指标的变动是由于策略差异所导致的结论。
多层实验
单层实验进行的最多实验数是有上限的,并且由于业务稳定的需求,尽量避免把所有的用户都同时置于实验之中。多层实验就是在单层实验的基础上发展而来。
多层实验的核心是用户分群,在单层用户的基础上,对用户ID进行重新分配,保证同一层不同分桶内的用户是均匀的,且任意两层的用户是正交的,此时每一层正在进行的实验都可以看做是一个单层实验,多层实验大大拓展了可同时进行实验的个数。多层实验的层数取决于用户分群算法的优劣,以及进行实验的关联性等。
(五)数据接口管理
(六)数据出口管理
(七)数据规划
数据实时化
数据资产化
数据服务化
数据智能化
(一)上报治理
(二)参数治理
(三)指标治理
指标治理来到了数仓层面,同样是由于缺乏统一规范,导致相似度很高的指标,以不同的名称在多张表中呈现,给下游的使用带来疑惑。
解决的方向之一是建立统一指标库,新增指标需要进行评审才能加入指标库并进行开发。个人认为更健康的方式应该是加深数仓和下游团队彼此的理解和信任,有些比较定制化的业务指标,可以由业务方先行计算并验证其可行性,不需要从一开始就固化在数仓层面;经过验证并确认有效的,数仓同学要想办法将其融合进现有数仓。
(四)流程治理
在业务已经比较成熟的数据团队内,规范化数据开发流程可以一定程度上避免野蛮开发,提高迭代效率。DataOps是一种协作数据管理实践,将数据开发、管理、分析、运营融为一体的方法论,通过更好的协作和自动化来改善组织对于数据的使用。
目前的问题在于数据开发者平台在更底层还要借助公司内各种数据平台才能实现数据的加工计算,所以和已有数据平台的对接及用户使用友好度这里还有待提升。
(五)成本优化
定期回顾数仓计算任务,合并类似的计算任务。 基础流水的解析,在实时任务保障稳定的前提下,离线任务可以不用例行化执行,仅作为实时任务的备份。 合理设置计算任务的所需资源,避免任务申请远超于实际需求的计算资源。 适当地用视图代替实际计算。
根据数据表下游使用情况,合理设置生命周期。 针对下游数据使用的时效性,合理选择存储引擎。 及时下线数仓中已失效的字段。 适当地使用视图代替实体表。
(六)价值循环
结语
推荐阅读
点击下方空白 ▼ 查看明日开发者黄历