2、实时数仓方案
2.1、为何需要实时数仓架构
随着数据量的增大,传统数据的方案在时效性上和数据维护上变得越来越困难。实时数仓架构应运而生。
具体方案落地上实时数仓有很多方案可以选择,不同的业务和应用场景到底应该选择哪种技术方案?
针对该问题梳理了市场上常见的实时数仓方案和对应的应用场景。
数仓一般分为:ODS层、DWD层、DWS层和ADS层。
1)ODS层:ODS是数据接入层,所有进入数据的数据首先会接入ODS层。一般来说ODS层的数据是多复杂多样的。从数据粒度上看ODS层是粒度最细的数据层。
2)DWD层:为数据仓库层,数据明细层的数据应是经过ODS清洗,转后的一致的、准确的、干净的数据。DWD层数据粒度通常和ODS的粒度相同,不同的是该层的数据质量更高,字段更全面等。
3)DWS层:数据集市层,面向主题来组织数据的,通常是星形或雪花结构的数据。从数据粒度来说,这层的数据是轻度汇总级的数据,已经不存在明细数据了。
4)ADS层:数据应用层,它是完全为了满足具体的分析需求而构建的数据,也是星形或雪花结构的数据。从数据粒度来说是高度汇总的数据。其汇总的目标主要是按照应用需求进行的。
为什么要分层,分层后有哪些好处呢?
数仓分层的总体思路是用空间换时间,其目的是通过数仓分层,使得数仓能够更好地应对需求的变更,和提高数据的稳定性。
1)用空间换时间:通过大量的预处理来提升应用系统的用户体验(效率),因此数据仓库会存在大量冗余的数据。
2)能更好地应对需求的变更:如果不分层的话,如果源业务系统的业务规则发生变化,将会影响整个数据清洗过程,工作量巨大。
3)提高数据处理过程的稳定性:通过数据分层管理可以简化数据清洗的过程,因为把原来一步的工作分到了多个步骤去完成,相当于把一个复杂的工作拆成了多个简单的工作,每一层的处理逻辑都相对简单和容易理解。
实时数仓其实是从Lambda(Lambda Architecture)架构演化而来的,首先了解Lambda架构。
Lambda架构将数据分为实时数据和离线数据。
实时数据使用流式计算引擎进行计算(例如Flink);
离线数据使用批量计算引擎(例如Spark)计算。然后分别将计算结果存储在不同的存储引擎上对外提供数据服务。
优点:是离线数据和实时数据各自计算,既能保障实时为业务提供服务,又能保障历史数据的快速分析。它分别结合了离线计算引擎与流式计算引擎二者的优势。
缺点:是离线数据和实时数据的一致性比较难保障,一般在离线数据产生后会使用离线数据清洗实时数据来保障数据的强一致性。
基于Lambda架构上的优化版本,Kappa架构。这种架构将数据源的数据全部转换为流式数据,并将计算统一到流式计算引擎上。
特点使架构变得更加简单,但是不足之处是需要保障数据都是实时的数据,如果数据是离线的话也需要转化为流式数据的架构进行数据处理,具体架构可结合这张图来看。
实时数仓的查询需求看
对实时数仓的主要需求:从更多维度上思考需求、条件、落地难点等等一些关键要素之间如何评估和权衡,最终实现是基于现有条件下的功能如何将其价值最大化。
传统意义上我们通常将数据处理分为离线的和实时的。对于实时处理场景,我们一般又可以分为两类:
- 一类诸如监控报警类、大屏展示类场景要求秒级甚至毫秒级;
- 另一类诸如大部分实时报表的需求通常没有非常高的时效性要求,一般分钟级别,比如10分钟甚至30分钟以内都可接受。
基于以上查询需求,业界常见的实时数仓方案有这几种。
项目大部分还在使用的标准分层体现+流计算+批量计算的方案。
大部会迁移到标准分层体系+流计算+数据湖,和基于全场景MPP数据库实现的方案上,重点介绍这两个方案。
Kappa架构将多源数据(用户日志,系统日志,BinLog日志)实时地发送到Kafka。
然后通过Flink集群,按照不同的业务构建不同的流式计算任务,对数据进行数据分析和处理,并将计算结果输出MySQL/ElasticSearch/HBase/Druid/KUDU等对应的数据源中,最终提供应用进行数据查询或者多维分析。
好处:方案简单;数据实时。
缺点:
- 一个是用户每产生一个新的报表需求,都需要开发一个Flink流式计算任务,数据开发的人力成本和时间成本都较高。
- 第二个是对于每天需要接入近百亿的数据平台,如果要分析近一个月的数据,则需要的Flink集群规模要求很大,且需要将很多计算的中间数据存储在内存中以便多流Join。
解决方案1中开发维护成本高等问题,出现基于标准分层+流计算的方案。
在传统数仓的分层标准上构建实时数仓,将数据分为ODS、DWD、DWS、ADS层。
首先将各种来源的数据接入ODS贴源数据层,再对ODS层的数据使用Flink的实时计算进行过滤、清洗、转化、关联等操作,形成针对不同业务主题的DWD数据明细层,并将数据发送到Kafka集群。
之后在DWD基础上,再使用Flink实时计算进行轻度的汇总操作,形成一定程度上方便查询的DWS轻度汇总层。最后再面向业务需求,在DWS层基础上进一步对数据进行组织进入ADS数据应用层,业务在数据应用层的基础上支持用户画像、用户报表等业务场景。
优点:各层数据职责清晰。
缺点:多个Flink集群维护起来复杂,并且过多的数据驻留在Flink集群内也会增大集群的负载,不支持upset操作,同时Schema维护麻烦。
解决方案2不支持upset和schema维护复杂等问题。在方案2的基础上加入基于HDFS加Spark离线的方案。也就是离线数仓和实时数仓并行流转的方案。
优点是:既支持实时的OLAP查询,也支持离线的大规模数据分析。但是带来了问题这样的几个问题。
数据质量管理复杂:需要构建一套兼容离线数据和实时数据血缘关系的数据管理体系,本身就是一个复杂的工程问题。离线数据和实时数据Schema统一困难。架构不支持upset。
解决数据质量管理和upset 问题。出现了流批一体架构,这种架构基于数据湖三剑客 Delta Lake / Hudi / Iceberg 实现 + Spark 实现。
以Iceberg为例介绍下这种方案的架构,从下图可以看到这方案和前面的方案2很相似,只是在数据存储层将Kafka换为了Iceberg。
特点,其中第2、3点,尤为重要,需要特别关注下,这也是这个方案和其他方案的重要差别。
01.在编程上将流计算和批计算统一到同一个SQL引擎上,基于同一个Flink SQL既可以进行流计算,也可以进行批计算。
02.将流计算和批计算的存储进行了统一,也就是统一到Iceberg/HDFS上,这样数据的血缘关系的和数据质量体系的建立也变得简单了。
03.由于存储层统一,数据的Schema也自然统一起来了,这样相对流批单独两条计算逻辑来说,处理逻辑和元数据管理的逻辑都得到了统一。
04.数据中间的各层(ODS、DWD、DWS、ADS)数据,都支持OLAP的实时查询。
Iceberg 能承担起实时数仓的方案呢,主要原因是它解决了长久以来流批统一时的这些难题:
1.同时支持流式写入和增量拉取。
2.解决小文件多的问题。数据湖实现了相关合并小文件的接口,Spark / Flink上层引擎可以周期性地调用接口进行小文件合并。
3.支持批量以及流式的 Upsert(Delete) 功能。批量Upsert / Delete功能主要用于离线数据修正。流式upsert场景前面介绍了,主要是流处理场景下经过窗口时间聚合之后有延迟数据到来的话会有更新的需求。这类需求是需要一个可以支持更新的存储系统的,而离线数仓做更新的话需要全量数据覆盖,这也是离线数仓做不到实时的关键原因之一,数据湖是需要解决掉这个问题的。
4.同时 Iceberg 还支持比较完整的OLAP生态。比如支持Hive / Spark / Presto / Impala 等 OLAP 查询引擎,提供高效的多维聚合查询性能。
前面的四种方案仍然属于比较复杂的,如果我能提供一个数据库既能满足海量数据的存储,也能实现快速分析;出现StartRocks、ClickHouse、Darios为代表的全场景MPP数据库。
1.基于Darios或者ClickHouse构建实时数仓。来看下具体的实现方式:将数据源上的实时数据直接写入消费服务。
2.对于数据源为离线文件的情况有两种处理方式,一种是将文件转为流式数据写入Kafka,另外一种情况是直接将文件通过SQL导入Darios、ClickHouse集群。
3. Darios、ClickHouse接入Kafka消息并将数据写入对应的原始表,基于原始表可以构建物化视图、Project等实现数据聚合和统计分析。
4.应用服务基于ClickHouse数据对外提供BI、统计报表、告警规则等服务。
在具体选型中,我们要根据具体业务需求、团队规模等进行技术方案选型。
(1)对于业务简单,且以流式数据为主数据流的大数据架构可以采用Kappa架构。
(2)如果业务以流计算为主,对数据分层,数据权限,多主题数据要求比较高,建议使用方案2的基于标准分层+流计算。
(3)如果业务的流数据是批数据都比较多,且流数据和批数据直接的关联性不大,建议使用方案3的标准分层体现+流计算+批量计算。这种情况下分别能发挥流式计算和批量计算各自的优势。
(4)方案4是一个比较完善的数仓方案,要支持更大规模的和复杂的应用场景,建议大数据研发人员在20以上的团队,可以重点考虑。
(5)对于大数据研发组团队为10人左右,要维护像方案2、3、4那样以ODS、DWD、DWS、ADS数据分层的方式进行实时数仓建设的话,就需要投入更多的资源。建议使用方案5一站式实现简单的实时数仓。
分享下OPPO、滴滴和比特大陆的方案,以便大家能够更好地理解这篇分享中五种架构的具体落地。
举例来说,OPPO的实时计算平台架构,其方案其实类似于方案2的基于标准分层+流计算。
滴滴的大数据平台架构是这样的,它的方案其实类似于方案2的基于标准分层+流计算。
再结合比特大陆的方案看下,其方案类型方案3的标准分层体现+流计算+批量计算,同时也引入了ClickHouse,可以看到比特大陆的数据方案是很复杂的。
3、为什么要分层
在实际的工作中,我们都希望自己的数据能够有顺序地流转,设计者和使用者能够清晰地知道数据的整个声明周期。优秀可靠的数仓体系,需要良好的数据分层结构。合理的分层,能够使数据体系更加清晰,使复杂问题得以简化。合理的分层概括就是:清晰的数据结构与依赖,提高开发效率,合理的数据权限。具体具有以下优点:
数据结构与依赖关系:如果没有清晰的分层,可能会做出一套表依赖结构混乱,且出现循环依赖的数据体系,让流程越走越越死。
减少重复开发的成本:建立一个或者多个模型,可以为支业务撑建立多个指标。规范数据分层,开发通用的中间层,可以极大地减少重复计算的工作。
统一数据口径:通过数据分层,提供统一的数据出口,统一输出口径。
数据一致性:对于公共下沉数据,下游使用的时候不再重新计算,可以保证一定是数据一致性问题。
数据权限:通过分层,可以更方便地对不同层,不同的数据模型进行权限管理,特定业务场景下,对不同的开发人员和业务人员屏蔽一些敏感的数据。
怎么分层
ODS(原始数据层)
存放最原始的数据,结构和源系统保持一致,减少对业务系统的影响。
DWD(明细数据层)
在维度建模的理论上进行构建,存放维度模型中的事实表,保存各业务过程最小粒度的操作记录。有时候,为了提高数据明细层的易用性,该层会采用一些维度退化手法,将维度退化至事实表中,减少事实表和维表的关联。
DIM(公共维度层)
在维度建模的理论上进行构建,存放维度模型中的维度表,保存一致性维度信息。维度类分两种类型(自己概括的):
大维度数据:比如用户维度等等
小维度数据:比如配置表,日期表,地区表等等
DWS(汇总数据层)
基于上层的指标需求,以分析的主题对象作为建模驱动,构建公共统计粒度的汇总表。该层的数据表会相对比较少,一张表会涵盖比较多的业务内容,由于其字段较多,因此一般也会称该层的表为宽表。主要作用就是提升指标的复用性,减少重复加工。单维度下的轻度汇总表维度单一,统计指标丰富,迭代更灵活;多维度的轻度汇总表,维度丰富,统计指标有限,迭代相对复杂。
ADS(数据应用层)
存放各项统计指标结果。
分层的误区
数仓层内部的划分不是为了分层而分层,分层是为了解决数据 任务及工作流的组织、数据的流向、读写权限的控制、不同需求的满足等各类问题。对于上面分层罗列,是种通用的建设分层逻辑。可能你也看到有四层的,有六层的,甚至更多的,比如DWD,DWB,DIM,DWM,MID......虽然每层你知道什么意思,但是有时候不是很清楚这些层之间的分割线是什么,出现复杂的业务反而让我们无法下手。所以各个业务不同,需要合适自己的就好。
所谓的宽表
经历几家公司,也听过好多公司,通常做法是把很多的维度、事实相关联后形成一个所谓的宽表。可能刚开始维度数据比较少,但是跟着业务的增长冗余维度增加,宽表足够的事实,足够的维度宽。带来影响就是没有清晰的表结构和随意增长的宽度。
所以,一些人开始强调划分主题,按照某一主题事实去扩展维度。也即宽表的涉及不依赖具体的业务需求而是根据整体业务线相匹配。
分层规则与规范
ODS
(1) 根据源业务系统表的情况以增量或全量方式抽取数据。
(2) 以统计日期和时间进行分区保存。
(3) 数据基本不做清洗和转换,数据的表结构和数据粒度与原业务系统保持一致。
DWD
(1)对数据做清洗、转换,脱敏等等处理,可以对表结构进行裁剪和汇总等操作。
(2)不是所有的数据都要永久保存,根据业务周期去做出决定。
DWD层中主要的事实表有三种类型 : 事务事实表、周期快照事实表和累积快照事实表。
事务型事实表
是什么
事务事实表用来记录各业务过程,跟踪时间上某点的度量事件,它保存的是各业务过程的原子操作事件,即最细粒度。
场景
事务型事实表可用于分析与各业务过程相关的各项统计指标,由于其保存了最细粒度的记录,可以提供最大限度的灵活性,可以支持无法预期的各种细节层次的统计需求。
不适合干什么
(1)存量型指标不适合
比如说商品库存,账户余额... 对于这种存在进进出出(加或减操作)不适合。一张存储商品的进货的原子操作事件,一张存储商品出库的原子操作事件。如果要统计当日的库存有多少,这就需要对进货表和出库表进行操作,需要一正一反地区分对库存的影响。所以在写代码或者sql过程还是执行效率都会打折扣。
(2)多事务关联统计不适合
比如在订单中,建立了下单事务事实表和支付事务事实表,现在指标统计某个时间内用户下单到支付的时间间隔的平均值,这就需要这两个表的Join操作,然而,订单在大型公司属于大表,大表 Join 大表 你可想而知。
周期型快照事实表
周期快照事实表以具有规律性的、可预见的时间间隔来记录事实,一般周期可以是每天、每周、每月、每年等。主要用于分析一些存量型或者状态型指标
场景
存量型:例如对于商品库存、账户余额这些存量型指标,业务系统中通常就会计算并保存最新结果,所以定期同步一份全量数据到数据仓库,构建周期型快照事实表,就能轻松应对此类统计需求。
状态型:例如对于空气温度、行驶速度这些状态型指标,由于它们的值往往是连续的,我们无法捕获其变动的原子事务操作,所以无法使用事务型事实表统计此类需求。而只能定期对其进行采样,构建周期型快照事实表。
累积型快照事实表
用来描述过程开始和结束之间的关键步骤事件,覆盖过程的整个生命周期,通常具有多个时间字段来记录关键时间点,当过程随着生命周期不断变化时,记录也会随着过程的变化而被修改。
场景
如交易流程中的下单、支付、发货、确认收货业务过程。会具体记录下单时间,支付时间,发货时间,收获时间。如果统计某个时间内用户下单到支付的时间间隔的平均值。这样就轻松搞定。
对比
- | 事务型事实表 | 周期型事实表 | 累积型快照事实表 |
---|---|---|---|
时间 | 离散事务时间 | 每天、每周、每月、每年等 | 多个时间字段来记录关键时间点 |
粒度 | 每行代表实体的一个事务 | 每行代表某时间周期的一个实体 | 每行代表一个实体的生命周期 |
数据加载方式 | insert | insert | insert/update |
DIM
(1) 维度在不同的业务表中的字段名称、数据类型、数据内容必须保 持一致。
(2)可以将维度与关联性强的字段进行整合,一种是水平整合:不同的表包含不同的数据,会使得维度本身的记录数变多,是对原有维度的记录数上的补充。另一种是垂直整合:不同的来源表包含相同的数据集,维度本身记录数不会变,只是会对维度属性进行补充。
(3)拆分针对重要性,业务相关性、源、使用频率等可分为核心表、扩展 表。一种是水平拆分:两个业务相关性低,整合在一起会对模型的稳定性和易用性产生影响。另一种是垂直拆分:维度属性从落库时间,使用频次,等等因素考虑上需要进行拆分放到子维度上。
DWS
(1)存放比较全的历史数据,业务发生变化时易于扩展,适应复杂的实际业务情况。
(2)尽量减少数据访问时的计算量,优化表的关联。
(3)可以有数据冗余。
(4)不要在同一个表中存储不同粒度的聚集数据。
ADS
(1)数据公用性。
(2)清晰明了的统计周期。
(3)等你补充......
4、数据仓库的分层架构
简介:分层架构很容易在各种书籍和文档中去理解,但是把建模方法和分层架构放在一起就会出现很多困惑了。接下来,我会从数据研发与建模的角度,演进一下分层架构的设计原因与层次的意义。
分层架构很容易在各种书籍和文档中去理解,但是把建模方法和分层架构放在一起就会出现很多困惑了。
之所以会有分层架构,最主要的原因还是要把复杂冗长的数据吹流程分拆成一些有明确目的意义的层次,这样复杂就被拆解为一些相对简单小的模块。那么分层架构中各层都是怎么产生的呢,我们可以简化看一下。
第一个数据加工任务
我要进行第一个数据加工任务,一切平台层次都没有,我只有一个MaxCompute。我该怎么做呢?
第一步,我需要自己做一下数据集成,把源系统的数据集成到MaxCompute。
第二步,我需要把增量合并全量生成ODS层,这样我就得到了与业务系统一样的表结构和全量的数据。
第三步,因为我对业务系统的数据表关联关系有了解,所以,我可以根据业务需求使用ODS的全量表做表关联,加工出我想要的数据结果。
第一个数据应用
如果我不只是做一个业务需求,我是有很多业务需求,这样我就形成了我的第一个数据应用。所以,我会集成更多的数据,做更多的数据合并全量的工作,并且我的全量ODS的表可以在多个业务场景复用。
但是试想一下,如果不是一个人在开发,那么团队内部是不是要协调一下,对工作进行一下分工。做集成的和做合并的是不是可以分给一部分人,然后把后面业务需求开发再分给另外一部分人。这样就避免了重复工作,和便于工作的专业性。
于是就可以拆分出来上图中的第一个方块“集成”(STG)和第二个方块 “全量”(ODS),这部分是纯技术性的工作,还没有涉及到业务需求。对于实际业务需求计算部分,就是我们的应用层集市层(ADM)。
第二个数据应用
随着第二个数据应用的出现,各自做集成合并已经是非常不适合的做法了,于是就有个独立的STG和ODS层。
很多时候,做完ODS就可以做业务数据加工了。并且这种情况从数据处理技术发展之初,数据仓库概念提出之前就存在了,现在依然很普遍。集市各自依赖ODS会遇到的多源加工指标不一致的问题逐渐遭人诟病,而造成指标不一致的主要原因重复加工。不同的人对同一业务的理解都很难保障一致性,更何况不同的部门的应用。对于这个问题,可以在各个大型企业早期的数据场景都会遇到,所以,在阿里对外宣传大数据平台的时候也会提到这个早期各个业务部门数据口径不一致的问题。这个问题在ODS的层面无法解决,必须要独立出一个团队来做公共的这部分数据,让各个应用集市去做各自独立的部分,这也是公共层(CDM)的由来。
二、分层与建模
通过上面的内容,我们终于知道了数据加工过程为什么要分层。那么数据建模应该如何来做呢?因为在数据仓库领域,在数据建模一直有两种争锋相对的观点,就是范式建模还是维度建模。我们在目前大数据这个场景,一般就只提一种方法了,就是维度建模。
维度建模的经典方法与教程中没有中间层的概念,也没有主题域划分的概念。维度建模一般用在数据集市场景,也就是ODS+ADM场景,各个业务通过一致性维度实现企业级的数据一致性。在传统的被IOE统治的时代,Teradata、IBM、Oracle都有基于关系型数据库(包括MPP数据库),在某些重要的行业,例如金融这些企业都会构建大型的企业级的维度模型来给集市提供公共数据服务,这就是公共层。因为范式模型导致实体都比较窄,跟实际的分析型业务需求(维度模型)差异太大,所以需要做一层中间层(相对范式模型更宽的表,这也是宽表说法的由来)来做为应用集市层共性加工工作的层次,这就是现在我们在架构中提到的ODS+CDM+ADM的架构。
那么问题就在这里出来了,我们全部使用维度模型建模,如何使用范式模型的架构与概念。这也是我们在分层架构设计中目前最难以讲清楚的问题,也是我们实际在项目里面做的很别扭的原因:缺乏理论与实践支撑。
维度模型的构建是以实际业务需求为导向,模型是不断的需求累积出来的,适应快速的业务变化。而且维度模型不是一个建议一开始就进行企业级的思考设计的模型设计方法,是由局部业务逐渐扩张构建的。所以,我认为维度模型的架构不太适宜一开始做太重的太业务化公共层。反而应该强调在公共层构建共性加工的集合,去协调同步多个应用集市的计算,从而实现全局性的一致性维度和一致性事实。因为维度建模的建设也不是简单一蹴而就的,也是需要多次和多种数据处理以后才能最终变成符合业务需求的结果。多个不同的应用集市有大量的共性的加工需求,这些需求就是我们公共层的收集的建模需求。把这些共性需求在公共层使用维度建模的方法实现才是建设公共层的合理方法,而不是越俎代庖的去建设面向具体某个业务场景的指标标签(就是虽然实际是做了指标和标签的计算,但是我只是一个中间加工过程)。
接下来,我们继续利用上面讲解分层的方法来讲解公共层与集市层的关系。
第一个应用
随着第一个应用出现,就可以基于部分的需求构建第一个公共层了。共性加工需求在一个中型的应用集市就很明显了。一、数据清洗。一个表的数据清洗后,会有多个数据加工任务都会使用这个清洗后的表,这就是最简单的共性加工的理解。二、多表关联。多张表的关联也是多个数据加工任务中可以提炼出来的,一次把需要关联使用的字段都关联合并到一张新表,后续的任务就可以直接用这个新表。三、共性汇总。对于数据从明细到汇总的group by,统一根据多个常用条件进行汇总,生成一张新表,后续的任务就可以直接用这个新表。一致性维度是维度建模中最关键的部分,直接影响到各个应用集市的数据标准与一致性问题,是公共层最重要的工作。
第二个应用
随着应用的增加,需求也在不断的扩充,临时层和镜像层集成的表更多了。在公共层的明细和汇总也出现了多个应用集市都在共用的数据需求,会扩展补充到公共层。并且随着时间的变化,公共层的逻辑的正确性和公共性也需要在多个应用进入后整体考虑。
公共层与应用关系
通过上面两步演进,我们已经看到了公共层与应用层的关系了,是一体的。并不是各做各的,而是一件事情从专业化分工上做了切分。公共层与应用层只有一个共同目标,就是为满足业务需求而做数据加工。不同侧重的是应用层只需要关注自己部门的最终业务目标,公共层则需要从企业级的全局一致性、资源经济性上全盘考虑。
公共层与应用层的关系就是后勤部队与前方作战部队的关系,一个负责基础的材料准备工作,一个负责利用这些输出投入到真实战场。公共层是高效的数据复用和综合更低的资源代价,应用层则就是实际的业务需求。所以,最终的业务模型在应用层才有完整的针对性业务场景,在公共层是模型是多种场景业务需求的一个复合,代表了平台最基础和最通用的模型。
从层次上来说,公共层向下是一块整体,负责跟上游多个交易型业务系统对接,对应用集市屏蔽了上游变化带来的影响,使得应用层能只关注于利用公共