《数据仓库》一文读懂数据仓库建设

这篇具有很好参考价值的文章主要介绍了《数据仓库》一文读懂数据仓库建设。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

数据仓库建设

数据仓库建设思维导图

一、数据仓库概念

1.数仓架构

​ 我们在谈到数据仓库,都会提到数仓架构,那么数仓架构到底是什么呢?首先,架构就是把一个整体工作按需切分成不同部分的内容,由不同角色来完成这些分工,并通过建立不同部分相互沟通的机制,使得这些部分能够有机的结合为一个整体,并完成这个整体所需要的所有活动。而数仓架构就可以理解为是构成数据仓库的组件以及之间的具有交互机制的关系。

数仓建设,离线数仓,实时数仓,大数据

​ 如上图所示,数仓的数据源可能来自业务系统的数据,或者外部获取的数据,或者从线下文件导入的数据。通过抽取工作,将这些数据存储到数仓的原始数据层中,并存储根据ETL、转换、处理等操作后的数据。在整个过程中,调度平台功能主要实现数据抽取和ETL等处理操作中需要定时完成的任务。而查询引擎功能主要实现快速的查询分析。报表展示功能主要是对数仓中最终的数据做结果展示。

2.数仓概念

数据仓库的目的就是统筹企业中所有的可以使用的数据,构建面向分析的集成化的数据环境,并通过分析结果为企业提供决策支持。数据仓库本身而言,它是不生产数据,也不消费数据的。数据来源于外部,通过数仓中一系列的运算操作,并将数据提供给外部。

基本特征

​ 数据仓库是面向主题的(Subject-Oriented)、集成的(Integrated)、非易失的(Non-Volatitle)和时变的(Time-Variant)数据集合,用于支持管理决策

1)主题性

​ 数据仓库是一般从用户实际需求出发,将不同平台的数据源按设定主题进行划分整合,与传统的面向事务的操作性数据库不同,具有较高的抽象性。面向主题的数据组织方式,就是在较高层次对分析对象数据的一个完整、统一并一致的描述,能完整及统一的刻画各个分析对象所涉及的有关企业的各项数据,以及数据之间的联系。

2)集成性

​ 数据仓库中存储的数据大部分来源于传统的数据库,但并不是将原有数据简单的直接导入,而是需要进行预处理。进行预处理的原因主要是源数据一般会存在不完整以及数据格式不统一的现象。这些脏数据会造成数据仓库中数据的混乱,不利于数据分析和挖掘操作。所以在其进入数据仓库前必须进行抽取、清洗、转换,才能实现从面向事务转而面向主题的数据集合。所以数据集成是数据仓库建设中极其重要而又复杂的一步。

3)稳定性

​ 数据仓库中的数据主要是为决策者分析提供数据依据。决策依据的数据是不允许随意修改。数据的更新调整主要在数据集成环节完成,一旦进入数据仓库后,用户仅能通过分析工具进行查询和分析。

4)动态性

​ 数据仓库数据会随着时间变化而定时更新,这里就是采用调度工具定时调度执行任务。按照设定的时间, 哦那个原始数据平台中抽取数据,转换后集成到数据仓库。随着时间的变化,数据以更高的综合层次被不断综合,以适应趋势分析的要求。当数据超过数据仓库的存储期限,或对分析无用时,从数据仓库删除这些数据。关于数据仓库的结构和维护信息保存在数据仓库的元数据中,数据维护工作由系统根据其中的定义自动进行或者由系统管理员定期维护。

3.数仓建设的目的

​ 想要了解数仓建设的目的,首先了解没有数仓建设之前的状况。数仓的数据往往用来为后面的即席查询、分析系统、数据集市、报表系统、数据挖掘系统做准备。在没有数仓建设之前,他们确实是直接对业务系统的数据做如此的操作,但是这样简单的访问,却会造成大量的问题。比如:

  • 部分的业务系统都设置有权限,出于安全原因你不能直接访问

  • 业务系统每次做版本升级,相应的报表系统还要进行再次测试

  • 企业中用于多个业务系统,那么对应的多个报表系统的维护问题

  • 不同业务系统之间形成数据孤岛,不能进行数据互通

  • 业务系统的数据格式等问题

  • 业务系统的数据存在脏数据的问题

  • 直接操作业务数据做分析,对数据而言也是一种危险

    从以上问题可知,虽然建设数仓初期会有大量的投入,但是当数仓步入正轨后,其效果和优势也是十分明显的。

4.OLAP和OLTP

OLTP

​ 联机事务处理OLTP,主要执行基本日常的事务处理,比如数据库记录的增删改查。

​ OLTP的特点:

  • 1.实时性要求高,例如银行业务中的转账实时到账。

  • 2.数据量小,一般生产库的数据量不是太大,而且回做相应的数据处理和转移。

  • 3.交易一般是确定的,比如银行存取款的金额肯定是确定的,所以OLTP是对确定性的数据进行存取

  • 4.高并发,并且要求ACID原则。比如两人同时使用一个银行卡账户,或者大型的购物网站秒杀活动QPS请求

    ACID:原子性(Atomicity),一致性(Consistency),隔离性(Isolation),持久性(Durability)

OLAP

​ 联机分析处理OLAP是数据仓库的主要应用,支持复杂的分析操作,侧重于决策支持,并且提供直观易懂的查询结果。典型的就是复杂的动态报表系统。

​ OLAP的特点:

  • 1.实时性要求不是很高,最常见的就是天级更新数据,然后对应的数据报表
  • 2.数据量大,因为OLAP支持的动态查询,所以用户也许要通过将许多数据统计后才能知道信息。
  • 3.OLAP系统的重点是通过数据提供决策支持,所以查询都是动态的,自定义的。所以在OLAP中,维度的概念特别重要。一般会将所有关心的维度数据,存入对应的数据平台。

总结

OLTP即联机事务处理,主要使用在业务系统中。

OLAP即联机分析处理,是数据仓库的核心部分。

5.数据仓库分层

​ 按照数据流入流出来看的话,大致可分为三层,分别是源数据层,数据仓库层,数据应用层。

源数据层

​ 一般是从业务系统抽取的数据、或者通过接口获取、或者通过线下导入,这里是无需做任何修改。

数据仓库层

​ 这一层可以成为细节层,DW层的数据应该是一致的、准确的、干净的数据,即对源数据进行了清洗后的数据

数据应用

​ 报表平台直接读取的数据源;根据报表、专题分析需求而计算生成的数据。

疑问解答?

​ 为什么要分层呢,这不是增加管理困难?

  • 首先分层可以实现用空间换时间,通过大量的预处理来提升应用系统的用户体验,因此数据仓库回存在大量冗余的数据;不分层的话,如果源业务系统的业务规则发生变化,会影响整个清理过程,增加工作量。
  • 其次通过数据分层管理可以简化数据清晰的过程,因为把原来一步的工作分到多个步骤去完成,相当于把一个复杂的工作拆分成多个简单的工作。

6.数仓架构演变

数据集市架构

​ 数据集市架构是按主题组织的数据集合,用于支持部门级别的决策。有两种类型的数据集市:独立数据集市和从属数据集市。

独立数据集市

​ 独立数据集市集中于部门所关系的单一主题域,数据以部门为基础部署,无需考虑企业级别的信息共享与集成。例如:营销部、人力资源部、制造部都有各自的数据集市。

​ 优点是:数据量小、周期短、见效快。

​ 缺点是:部门之间的指标不同、部门之间交互能力差、跨部分分析难

数仓建设,离线数仓,实时数仓,大数据

从属数据集市

​ 从属数据集市的数据来源于数据仓库。数据仓库里的数据经过整合、重构、汇总后传递给从属数据集市(也就是各个部门的数据集市)

​ 优点是:当数据仓库的查询性能出现问题,可以通过建立多个从属数据集市,减少数据仓库的压力。每个部门都能管理自己的数据集市。因为每个数据都来源于同一个数据仓库,有效消除数据不一致的问题。

数仓建设,离线数仓,实时数仓,大数据

Inmon企业工厂架构

​ 这个架构跟独立数据集市很像,主要区别在于在部门级数据集市之前添加了企业级数据仓库。而企业级数据仓库是一个细节数据的集成资源库。其中的数据以最低粒度级别被捕捉,存储在满足三范式涉及的关系数据库种。

数仓建设,离线数仓,实时数仓,大数据

Kimball数据仓库架构

数仓建设,离线数仓,实时数仓,大数据

​ 如上图所示,Kimball与Inmon两种架构的主要区别在于核心数据仓库的设计和建立。

​ Kimball的数据仓库包含高粒度的企业数据,使用多为模型设计,这也意味着数据仓库由星型模型的维度表和事实表构成。分析系统或者报表工具可以直接访问多维数据仓库里的数据。这里的数据集市跟Inmon架构中的数据集市不同,这里的数据集市是一个概念,只是多维数据仓库中的主题划分,并没有自己的物理存储,也可以说是虚拟的数据集市。

混合型数据仓库架构

所谓混合型架构,就是联合使用Inmon和Kimball这两种架构

数仓建设,离线数仓,实时数仓,大数据

​ 如上所示,这种架构将Inmon方法中的数据集市替换成一个多维的数据仓库,而数据集市则是多维数据仓库上的逻辑视图。

​ 优点是:既可以利用规范式设计消除数据冗余,保证数据的粒度够细;又可以充分利用多维结构来更灵活的在企业级数仓中实现分析和展示。

第一范式:要求消除拆分字段至原子字段,即不可再拆分

第二范式:要求消除部分函数依赖,实现完全函数依赖

第三范式:要求消除传递函数依赖

函数依赖:A列属性跟主键有关系

部分函数依赖:A列函数只跟主键的部分属性有关系

完全函数依赖:A列属性只跟主键的全部属性有关系

传递函数依赖:A列属性跟B列属性有关系,B列属性跟主键有关系

7.元数据管理

元数据管理是企业数据治理的基础,是数据仓库的提升。元数据中定义了数据仓库的模式、来源、抽取以及转换规则,在整个数据仓库的基础之上,把各个松散的组件,组成一个有机的整体。

​ 元数据(MetaData),又称为是中介数据、中继数据,为描述数据的数据。

​ 另一种解释就是:一组用于描述数据的数据组,该数据组的一切信息都描述了该数据的某方面的特征,则该数据组即可被称为元数据。

技术元数据

​ 技术元数据为开发和管理数据仓库的IT人员使用,它描述了与数据仓库开发、管理和维护相关的数据,包括数据源信息、数据转换描述、数据仓库模型、数据清洗、更新规则、数据映射、访问权限等。

业务元数据

​ 业务元数据为管理层和业务分析人员服务,从业务角度描述数据,包括商务术语、数据仓库中有什么数据、数据的位置和数据的可用性等,帮助业务人员更好的理解数据仓库中哪些数据是可用的以及如何使用。

二、离线数仓建设核心

1.数仓分层

数仓分层的原则:

  • 空间换时间,通过大量的预处理来提升应用系统的用户体验
  • 便于数据分析,屏蔽底层复杂业务,将简单、完整、有效的数据暴漏给分析层
  • 削弱底层业务变动对整体模型的影响
  • 高内聚低耦合,主题之内数据高内聚,主题之间数据低耦合
  • 层次分明,便于管理,为数据仓库大规模开发奠定基础

数仓建设,离线数仓,实时数仓,大数据

1.数据源层:ODS(Operational Data Store)

​ ODS层,是最接近数据源中数据的一层,为了考虑后续需要追加数据的问题,这一层不对数据做任何处理。

2.数据仓库层:DW(Data Warehouse)

​ 数据仓库层是我们在做数据仓库的时候要设计的最核心的一层。在这里,从ODS层中获得的数据按照主题建立各种数据模型。DW层又细分为DWD(Data Warehouse Detail)、DWM(Data Warehouse Middle)、DWS(Data Warehouse Service)

1)数据明细层:DWD

​ 该层一般保持和ODS层一样的数据粒度,并提供一定的数据质量保证。DWD层要做的就是将数据清理、整合、规范化、脏数据、垃圾数据、不规范数据、状态不一致数据、命名不规范数据都会被处理。

​ 同时,为提高数据明细层的易用性,该层会采用一些维度退化的手法,将维度退化至事实表,减少事实表和维表之间的关联。

​ 在该层也会做部分的数据聚合,将相同主题的数据汇集到一张表中,提高数据的可用性。

tips:维度退化:当一个维度没有数据仓库需要的任何数据时,就可以退化维度。需要把退化的维度的相关数据迁移到事实表中,然后删除退化的维度

2)数据中间层:DWM(Data WareHouse Middle)

​ 该层会在DWD层的数据基础上,数据做轻度的聚合操作,生成一系列的中间表,提升公共指标的复用性,减少重复加工。

​ 直观来讲,就是对通用的核心维度进行聚合操作,算出对应的统计指标

​ 在实际的计算中,如果直接从DWD或者ODS计算出宽表的统计指标,会存在计算量太大并且维度太少的问题。因此一般的做法是,在DWM层先计算多个小的中间表,然后再拼接成一个DWS的宽表。由于宽和窄的界限不易界定,也可以去掉DWM这一层,只留DWS层,将所有的数据再放在DWS层亦可。

tips:根据企业宽窄界定,可有可无

3)数据服务层:DWS(Data WareHouse Service)

​ DWS层为公共汇总层,会进行轻度汇总,粒度比明细数据稍粗,基于DWD层上的基础数据,整合汇总分析某一个主题域的服务数据,一般是宽表。DWS层应覆盖80%的应用场景,又称为数据集市或宽表。

​ 按照业务划分,如主题域流量、订单、用户等,生成的字段比较多的宽表,用于提供后续的业务查询,OLAP分析,数据并发。

​ 一般来讲,该层的数据表相对较少,一张表会涵盖较多的业务内容,由于其字段较多,因此一边拿会称该层的表为宽表。

4)数据应用层:APP(Application)

​ 在这里,主要是提供给数据产品和数据分析使用的数据,一般会存放在ES、PostgreSql、Redis等系统中供线上系统使用,也可能会存在Hive或者Druid中供数据分析和数据挖掘使用。

5)维度表:DIM(Dimension)

​ 如果维表过多,也可以针对维表设计单独的一层,维表主要包含两部分数据:

​ **高基数维度数据:**一般是用户资料表、商品资料表类似的资料表。数据量可能是千万级别或者上亿级别。

​ **低基数维度数据:**一般是配置表,比如枚举值对应的中文含义,或者日期维表。数据量可能是个位数或者几千几万。

2.数仓建模

​ 数仓建模主要是在DW层进行数仓建模,所以DW层是数仓建设的核心层。

​ 常见的建模方法有范式建模、维度建模、实体类建模,从不同的角度看待业务问题。

1)范式建模法

​ 范式建模法其实是我们在构建数据模型常用的一种方法,该方法的主要由Inmon所提倡,主要解决关系型数据仓库的数据存储,利用的一种技术层面上的方法。目前,在关系型数据库中的建模方法,大多数采用的第三范式建模法。

​ 范式是符合某一级别的关系模式的集合。构造数据库必须遵循一定的规则,而在关系型数据库中这种规则就是范式,这一过程也被成为规范化。在数据仓库的模型设计中,一般采用第三范式。而第三范式要满足以下条件:

  • 每个属性值唯一,不具有多义性
  • 每个非主属性必须完全依赖于整个主键,而非主键的一部分
  • 每个非主属性不能依赖于其他关系中的属性,因为这样的话,这种属性应该归到其他关系中。

数仓建设,离线数仓,实时数仓,大数据

​ 如上图所示,根据Inmon的观点,数据仓库模型的建设方法和业务系统的业务数据模型类型。在业务系统中,企业数据模型决定了数据的来源,而企业数据模型也分为两个层次,即主题域模型和逻辑模型。同样,主题域模型可以堪称是业务模型的概念模型,而逻辑模型则是域模型在关系型数据库上的实例化

2)维度建模法

​ 维度模型是数据仓库领域另一位大师Ralph Kimall所倡导,他的《数据仓库工具箱》是数据仓库领域最流行的数仓建模经典。维度建模以分析决策的需求出发构建模型,构建的数据模型为分析需求服务,因此它重点解决用户如何更快完成分析需求,同时还有较好的大规模复杂查询的响应性能。

数仓建设,离线数仓,实时数仓,大数据

​ 在维度建模中最为典型的就是星型模型,还有在特殊场景用到的雪花模型星座模型

​ 维度建模中比较重要的概念就是事实表和维度表。其最简单的描述就是,按照事实表、维度表来构建数据仓库、数据集市。

3)实体建模法

​ 实体建模法并不是数据仓库建模常见的一种方法,它来源于哲学的一个流派。从哲学的意义上说,客观时间应该是可以细分的,客观世界应该可以分成由一个实体,以及实体与实体之间的关系组成。那么我们在数据仓库的建模过程中完全可以引入这个抽象的方法,将整个业务划分为一个个的实体,而每个实体之间的关系,以及针对这些关系的说明,就是我们数据建模需要做的工作。

数仓建设,离线数仓,实时数仓,大数据

​ 如上图所示,虽然实体法粗看有些抽象,其实理解起来很容易。即我们可以将任何一个业务过程划分成三个部分,实体、事件、说明

3.维度建模详解

​ 目前在互联网公司中最常用的建模方法就是维度建模。维度建模适用于分析性数据库、数据仓库、数据集市(小型数据仓库)建模的方法。在开始建模之前,应先了解维度建模中表的类型维度建模的模式,有利于我们更深刻的理解。

维度建模中表的类型

​ 维度建模中的表主要为两种:事实表和维度表

  1. 事实表:必然存在的一些数据,像采集的日志文件,订单表,都可以作为事实表

    特征:是一堆主键的集合,每个主键对应维度表中的一条记录,客观存在的,根据主题确定出需要使用的数据

  2. 维度表: 维度表就是所分析的数据的一个量,维度表就是以合适的角度来创建的表,分析问题的一个角度:时间、地域、终端、用户等角度。

1)事实表

​ 发生在现实世界中的操作型事件,其所产生的可度量数值,存储在事实表中。最低的粒度级别来看,事实表对应一个度量事件,反之亦然。事实表表示对分析主题的度量。比如一次购买行为我们就可以理解为是一个事实。

数仓建设,离线数仓,实时数仓,大数据

​ 如上图所示:订单表就是一个事实表,他记录的就是现实中的一个操作性的事件。从这里可以看出,表里并没有存储具有实际意义的数据。这些主键的集合,通过每一个主键都可以获取一个相关维度的数据。事实表的度量通常是数值类型,且记录数会不断增加,表数据规模迅速增长。

1.1)事实表-明细表(宽表):

​ 事实表的数据中,有些属性共同组成了一个字段(糅合在一起),比如年月日时分秒构成了事件,当需要根据某一属性进行分组统计的时候,需要截取拼接之类的操作,效率极低,如:

create_time
2022-03-17 10:12:11

​ 为了方便根据其中某一属性进行分组统计(例如按照月统计生成单数),可以在事实表中的一个字段切割提取多个属性构成新的字段,因为字段变多了,所以称为宽表,原来的为窄表。又因为宽表的信息更加清洗明细,所以也可以称其为明细表。

year month day hour m s
2022 03 17 10 12 11

1.2)事实表分类

  • 事务事实表

    表中的一行对应空间或时间上某点的度量事件。就是一行数据中必须有度量字段,什么是度量,就是指标,比如说销售金额,销售数量等这些可加或者半可加就是度量值。另一点就是事务表都包含一个与维度关联的外键。并且度量值必须和事务粒度保持一致。

  • 周期快照事实表

    周期事实表就是每行都带有时间值字段,代表周期,通常时间值都是标准周期,如某一天,某周,某月。粒度是周期,而不是个体的事务,也就是说一个周期快照事实表中数据可以是多个试试,打死你同属于一个周期内。

  • 累计快照事实表

    周期快照事实表是单个周期内的数据,而累计快照事实表是由多个周期数据组成的,每行汇总了过程从开始到结束之间的度量。每行数据都相当于管道或者工作流,有事件的起点、过程、终点,并且每个关键步骤都包含日期字段。如累计快照事实表的一行就算一个订单,当订单产生时插入一行,订单发生变化时,这一行就被修改。

  • 无事实的事实表

    在事实表中我们说到,事实表度量都是数字化的,但是可能会存在少数没有数字化的值但是很有价值的字段,无事实的事实表就是为这种数据准备的,利用这种事实表可以分析发生了什么。

  • 聚集事实表

    聚集,就是对原子粒度的数据进行简单的聚合操作,目的就是为了提高查询性能。如我们需要是查询全国所有门店的总销售额,我们原子粒度的事实表中每行是每个分店每个商品的销售额,聚集事实表就可以先聚合每个分店的总销售额,这样汇总所有门店的销售额时计算的数据量就会小很多。

  • 合并事实表

    这种事实表遵循一个原则,就是相同粒度,数据可以来自多个进程,但是只要他们属于相同的粒度,就可以合并成为一个事实表,这类事实表特别适合经常需要共同分析的多过程度量。

2)维度表

​ 每个维度表都包含单一的主键列。维度表的主键可以作为与之关联的任何事实表的外键。维度表通常比较宽,是扁平化非规范表,包含大量的低粒度的文本属性。

​ 维度表表示你要对数据进行分析时所用的一个量,比如你要分析产品销售情况,你可以选择按类别来分析,或按区域分析。每个类别就构成了一个维度。上图中的用户表、商品表】时间表这些都属于维度表,这些表都有一个唯一的主键,然后在表中存放详细的数据信息。

​ 总的来说,在数据仓库中不需要遵守规范化的设计原则。因为数据仓库的主导功能就算面向分析,以查询为主,不涉及数据更新的操作。事实表的设计是以能够正确记录历史信息为准则维度表的设计是以能够以合适的角度来聚合主题内容为准则。

  • 维度表结构

    维度表谨记一条原则,包含单一主键列,但是有时因业务复杂,也可能出现联合主键,请尽量避免。如果无法避免也要确保是单一的,这很重要。如果维度表主键不是单一的,和事实表关联时会出现数据发散,导致最后错误的结果。维度表通常比较宽,包含大量的低粒度文本属性。

  • 跨表钻取

    跨表钻取意思是当每个查询的行头都包含相同的一致性属性时,使用不同的查询能够针对两个或者更多的事实表进行查询

    钻取可以改变维度的层次,变换分析的粒度。它包括上钻/下钻:

    上钻(roll-up)(忽视维度):上卷是沿着维的层次向上聚集汇总数据。例如,对产品销售数据,沿着事件维上钻,可以求出所有产品在所有地区每月(或季度或年或全部)的销售额

    下钻(drill-down)(细化维度):下钻是上钻的逆操作,它是沿着维的层次向下,查看更详细的数据。

  • 退化维度

    退化维度就是将维度退回的事实表中。因为有时维度除了主键没有其他内容,虽然也是合法的维度键,但是一般都会退回到事实表中,减少关联次数,提高查询性能。

  • 多层次维度

    多数维度包含不止一个自然层次,如日期维度可以从天的层次到周到月到年的层次。所以在有些情况下,在同一维度中存在不同层次。

  • 维度表空置属性

    当给定维度行没有被全部填充时,或者当存在属性没有被应用到所有维度行时,将产生空置维度属性。上诉两种情况,推荐采用描述性字段代替空值,如使用unknown或not applicable替换空置。

  • 日历日期维度

    在日期维度表中,主键的设置不要使用顺序生成的id来表示,可以使用更有意义的数据表示,比如将年月日合并起来表示,即YYYYMMDD,或者更加详细的精度。

维度建模的三种模式

1)星型模型

​ 星型模型是最常用的维度建模方式。星型模型**以事实表为中心,所有维度表直接连接在事实表上,像星星一样,故称为星型模型。**星型模型的维度建模由一个事实表和一堆维度表组成,且具有以下特点:

  • 维表只和事实表关联,维表之间没有关联
  • 每个维表主键为单列,且该主键放置在事实表中,作为两边连接的外键
  • 以事实表为核心,维表围绕核心呈星型分布。

数仓建设,离线数仓,实时数仓,大数据

2)雪花模型

​ 雪花模型是对星型模型的扩展。雪花模型的维度表可以拥有其他维度表,虽然这种模型相比星型模型更加规范,但是由于这种模型不易理解维护成本高,而且性能方面需要关联多层维度表,性能也比星型模型要低。所以一般不是很常用。

数仓建设,离线数仓,实时数仓,大数据

3)星座模型

​ 星座模型是星型模型延伸而来,**星型模型是基于一张事实表,而星座模型是基于多张事实表,而且共享维度信息。**星型模型和星座模型都是多维表对应单事实表但在很多时候维度空间内的事实表不止一个,而一个维表也可能被多个事实表用到。在业务发展后期,绝大多数维度建模都是采用星座模型。

数仓建设,离线数仓,实时数仓,大数据

维度建模过程

​ 在维度建模的时候,表的类型主要分为事实表和维度表;模式有星型模型、雪花模型和星座模型。但是在实际业务中,如果拿到一堆的数据,怎么进行数据建设呢?

数仓工具箱中的维度建模四步走:

数仓建设,离线数仓,实时数仓,大数据

1)选择业务过程

维度建模是紧贴业务的,所以必须以业务为根基进行建模,那么选择业务过程,顾名思义就是在整个业务流程中选取我们需要建模的业务,根据运营提供的需求以及日后的易扩展性等进行选择业务。比如商城,整个商城流程分为商家端、用户端、平台端,运营需求是总订单量,订单人数,及用户购买情况。我们选择业务过程就选择用户端的数据,商家及平台端暂不考虑。业务选择非常重要,因为后面所有的步骤都是基于此业务数据展开的。

2)声明粒度

​ 先举个栗子:对于用户来说,一个用户有一个身份证号,一个户籍地址,多个手机号,多张银行卡。那么与用户粒度相同的粒度属性有身份证粒度,户籍地址粒度;比用户粒度更细的粒度有手机号粒度,银行卡粒度,存在一对一的关系就是相同粒度;为什么要提相同粒度呢?因为维度建模中要求我们,在同一事实表中,必须具有相同的粒度,同一事实表中不要混用多种不同的粒度,不同的粒度数据建立不同的事实表。并且从给定的业务过程获取数据时,强烈建议从关注原子粒度开始涉及,也就是从最细粒度开始,因为原子粒度能够承受无法预期的用户查询。但是上卷汇总粒度对查询性能的提升很重要,所以对于有明确需求的数据,我们建立针对需求的上卷汇总粒度,对需求不明朗的数据我们建立原子粒度。

3)确认维度

​ 维度表是作为业务分析的入口和描述性标识,所以也被称为数据仓库的“灵魂”。在一堆的数据中怎么确定哪些是维度属性呢,如果该列是对具体的描述,是一个文本或者常量,某一约束和行标识的参与者,此时该属性往往是维度属性,数仓工具箱告诉我们牢牢掌握事实表的粒度,就能将所有可能存在的维度区分开。并且要确保维度表中不能出现重复数据,应使维度主键唯一。

4)确认事实

事实表是用来度量的,基本都以数据量表示,事实表中的每行对应一个度量,每行中的数据是一个特定级别的细节数据,称为粒度。维度建模的核心原则之一是统一事实表中所有度量必须具有相同的粒度。这样能确保不会出现重复计算度量的问题。有时候往往不能确定该列数据是事实属性还是维度属性,记住**最实用的事实就是数值类型和可加类事实。**所以可以通过分析该列是否是一种包含多个值并作为计算的参与者的度量,这种情况下往往是事实。

三、离线数仓建设实战

技术是为业务服务,业务是为公司创造价值,离开业务的技术是毫无意义的

1.业务介绍

​ 需要针对不同需求的用户开发不同的产品,所以公司内部有很多条业务线,但是对于数据部门来说,所有数据线的数据都是数据源。对数据的划分不只根据业务进行,而是结合数据的属性。

2.早期规划

​ 之前开发是不同业务线对应不同的数据团队,每个数据团队互不干扰,这种模式比较简单,只针对自己的业务线进行数仓建设及报表开发即可。

​ 但是随着业务的发展,频繁迭代及跨部门的垂直业务单元原来越多,业务之间的出现耦合的情况,这时再采用这种烟囱开发就出现了问题:

​ 例如权限问题,公司对数据管理比较严格,不同的数据开发组没有权限共享数据,需要其他的业务线权限需要上报审批,比较耽误时间;

​ 还有重复开发的问题,不同业务线会出现相同的报表需求,如果每个业务方都开发各自的报表,太浪费资源。所以对于数据开发而言,需要对各个业务线的数据进行统一管理,所以就有了数据中台的出现。

3.数据中台

​ 数据中台的建设是根据每个公司的业务需求而搭建的,不同的业务,对中台的理解有所不同。公司内部开发的敏捷数据中台,主要从数据技术和计算能力的服用,到数据资产和数据服务的服用,数据中台以更大价值带宽,快精准直接赋能业务。提供一个统一化的管理,打破数据孤岛,追溯数据血缘,实现自助化及高复用度。

数仓建设,离线数仓,实时数仓,大数据

​ 以上解释比较抽象,可以以实际项目开发来分析数据中台的便利性。比如在整个流程中,首先是数据采集,不同的数据通过Sqoop、DataX、Kettle、Nifi等工具采集到大数据平台中,然后进行数仓搭建,最后产出报表数据,放到可视化系统中展示,最终把整个流程写成脚本放到调度平台进行自动化执行(例如Azkaban,Dolphin)。

​ 有了数据中台之后就不需要那么繁杂的事情,直接进行数仓搭建,产生报表即可,无需将精力浪费在数据源、可视化展示及调度。并且可以直观的查看数据血缘关系,计算表之间的血缘。如下图所示:

数仓建设,离线数仓,实时数仓,大数据

数据中台的异构数据系统可以非常简单的进行查询,比如Hive的表关联MySQL的表。可透明屏蔽异构数据系统交互方式,轻松实现跨异构数据系统透明混算。

异构数据系统原理是数据中台提供虚拟表之间的映射,终端用户无需关心数据的物理存放位置和底层数据源的特性,可直接操作数据,体验类似操作一个虚拟数据库。

4.数仓建设

​ 数仓建设是根据公司的业务发展以及现有的数据中台进行,数仓的建设离不开公司的业务。

智能数仓规划

​ 数仓建设核心思想:从涉及、开发、部署和使用层面,避免重复建设和指标冗余建设,从而保障数据口径的规范和统一,最终实现数据资产全链路关联、提供标准数据输出以及建立统一的数据公共层。

​ 数仓建设主要从两个方面,规模和规范,所有业务进行统一化。

1)模型

​ 所有业务采用统一的模型体系,从而降低研发成本,增强指标服用,并且能够保证数据口径的统一

2)模型分层

​ 结合公司业务,后期新增需求增多,所以分层不宜过多,并且需要清晰明确各自职责,要确保数据层的稳定又屏蔽对下游影响,所以采用分层结构:

数仓建设,离线数仓,实时数仓,大数据

数据分层架构

1)数据流向

遵循模型开发时分层结构,数据从ods->dw-dm-app这样正向流动,可以放置因数据引用不规范而造成数据链路混乱及SLA时效难保障等问题,同时保证血缘关系简单化,能够轻易追踪数据流向。在开发时应避免以下情况出现:

​ 1.数据链路引用不正确,如ods-dm-app,出现这种情况说明明细层没有完全覆盖数据;如ods-dw_app,说明轻度汇总主题划分未完全覆盖。减少跨层引用,才能提高中间表的复用性,理想的数仓模型设计应当具备:数据模型可复用,完善且规范。

​ 2.尽量避免一层的表引用当前层的表,如DW层的表生成DW层的表,这样会影响ETL效率。

​ 3.禁止出现反向依赖,如DW表依赖于DM表

2)规范

2.1)表命名规范

​ 1.对于ods,dm,app层表名:类型_主题_含义,如:dm_xxsh_user

​ 2.对于dw层表名:类型_主题_维度_表含义,如:dw_xxsh_fact_users(事实表)dw_xxsh_dim_users(维度表)

2.2)字段命名规范

​ 构建词根,词根是维度和指标管理的基础,划分为普通词根与专有词根

​ 1.普通词根:描述事物的最小单位,如:sex-性别

​ 2.专有词根:具备行业专属或公司内部规定的描述题,如:xxsh-公司内部对某个产品的称呼

​ 3.脚本命名规范:脚本名称:脚本类型.脚本共用.[库名].脚本名称,如hive.hive.dm.dm_xxsh_users

​ 脚本常用类型:1.hive sql 2.shell脚本 3.python脚本

5.数据层具体实现

1)数据源层ODS

数据源层主要将各个业务数据导入到大数据平台,作为业务数据的快照存储。

数仓建设,离线数仓,实时数仓,大数据

2)数据明细层DW

事实表中的每行对应一个度量,每行中的数据是都是特定级别的细节数据,称为粒度维度建模的核心原则就是同一事实表中所有度量必须具有相同的粒度。这样才能确保不会出现重复计算度量的问题。

维度表一般都是单一主键,少数是联合主键,注意维度表不要出现重复的数据,否则和事实表关联会出现数据发散的问题。

有时候往往不能确定该列数据是事实属性还是维度属性。记住最实用的事实就是数值类型和可加类事实。所以可以通过分析该列是否是一种包含多个值并作为计算的参与者的度量,这种情况下往往是事实字段。如果该列是对具体值的描述,是一个文本或常量,某一约束和行标识的参与者,此时该属性往往是维度属性。但是还要结合具体业务进行最终的判断是事实还是维度。

数仓建设,离线数仓,实时数仓,大数据

3)数据轻度汇总层 DM

此层命名为轻度汇总层,就代表这一层已经开始对数据进行汇总,但是不是完全汇总,只是对相同粒度的数据进行关联汇总,不同粒度但是有关系的数据也可以进行汇总,此时需要将粒度通过聚合等操作进行统一。

数仓建设,离线数仓,实时数仓,大数据

4)数据应用APP层

数据应用层的表是提供给用户使用的,数仓建设到此就接近尾声了,接下来就根据不同的需求进行不同的取数,如直接进行不同的取数,如直接进行报表展示,或提供给数据分析的同事的数据,或其他业务支撑。

数仓建设,离线数仓,实时数仓,大数据

6.总结

数仓建设,离线数仓,实时数仓,大数据

7.实际生产中注意事项

​ 实际环境中不能像测试环境一样随意,很容易造成生产事故。所以每一步操作都必须要小心,以下为简单列出的注意事项:

  • 请勿操作自己管理及授权表之外的库表
  • 未经授权,请勿操作生产环境中其他人的脚本及文件
  • 在修改生产环境脚本前,无比自行备份到本地
  • 请确认自己的修改操作能迅速回滚
  • 生产环境中表名及字段等所有命名请遵循命名规则

四、实时计算

​ 实时计算一般是针对海量的数据进行的,并且要求秒级。由于大数据兴起之时,Hadoop并没有给出实时计算的解决方案,随后的Stromberg,SparkStreaming,Flink等实时计算框架应运而生,而Kafka、ES的兴起也使得实时计算领域的技术越来越得到完善,而随着物联网,机器学习等技术的推广,实时流式计算在这些领域得到充分的应用。

实时计算的三个特征:

  • 1.无限数据:无线数据指的是一种不断增长的,基本上无限的数据集。这些通常被称为“流数据”,而与之相对的是有限的数据集。
  • 2.无界数据处理:一种持续的数据处理模式,能够通过处理引擎重复的去处理上面的无线数据,是能够突破有限数据处理引擎的瓶颈。
  • 3.低延迟:延迟是多少并没有明确的定义,但是我们都知道数据的价值将随着时间的流式降低,时效性将是需要持续解决的问题

现在大数据应用比较火爆的领域,比如推荐系统在实践之初受技术所限,可能要一分钟,一小时,甚至更久对用户进行推荐,这远远不能满足需要,我们需要更快的完成对数据的处理,而不是进行离线的批处理。

1.实时计算应用场景

​ 随着实时技术趋于成熟,实时计算应用越来越广泛,以下仅列举常见的各种实时计算的应用场景。

1)实时智能推荐

​ 智能推荐会根据用户历史的购买或浏览行为,通过推荐算法训练模型,预测用户未来可能会购买的物品或喜爱的咨询。对个人来说,推荐系统起着信息过滤的作用,对Web/App服务端来说,推荐系统起着满足用户个性化需求,提升用户满意度的作用。推荐系统本身也在飞速发展,除了算法越来越完善,对时延的要求也越来越苛刻和实时化。利用flink流计算帮助用户构建更加实时的智能推荐系统,对用户行为指标进行实时计算,对模型进行实时更新,对用户指标进行实时预测,并将预测的信息推送给Web/App端,帮助用户获取想要的商品信息,另一方面也帮助企业提升销售额,创造更大的商业价值。

2)实时欺诈检测

​ 在金融领域的业务中,常常出现各种类型的欺诈行为,例如信用卡欺诈,信贷申请欺诈登,而如何保证用户和公司的资金安全,是近年来许多金融公司及银行共同面对的调整。随着不法分子欺诈手段的不断升级,传统的反诈手段不足解决目前所面临的问题。以往可能需要几个小时才能通过交易数据计算出用户的行为指标,然后通过规则判别具有欺诈行为嫌疑的用户,再进行案件调差处理,在这种情况虾资金可能早被不发分子转移,从而给企业和用户造成德莱昂的经济损失。而运用flink流式计算技术能够在毫秒内就完成欺诈行为判断指标的计算,然后实时对交易流水进行实施拦截,避免因为处理不及时而导致经济损失。

3)舆情分析

​ 有的客户要做舆情分析,要求所有数据存放若干年,舆情数据每日数据量可能超百万,年数据量可达到几十亿的数据。而且爬虫爬过来的数据是舆情,通过大数据技术进行分词之后得到的可能是大段的网友评论,客户往往要求爬到大数据平台的Kafka里,在里面做Flink流处理,去重去噪做语音分析,写道ES里。大数据的一个特点是多数据源,大数据平台能根据不同的场景选择不同的数据源。

4)复杂事件处理

​ 对于复杂事件处理,比较常见的集中于工业领域,例如对车载传感器,机械设备登实时故障检测,这些业务类型通常数据量都非常大,且对数据处理的时效性要求更高。通过利用flink提供的CEP进行事件模式的抽取,同时应用Flink的SQL进行事件数据的转换,在流式系统中构建实施规则引擎,一旦事件触发报警规则,便立即将告警结果通知至下游系统,从而实现对设备故障快速预警监测,车辆状态监控等目的。

5)实时机器学习

​ 实时机器学习是一个更宽泛的概念,传统静态的机器学习主要侧重于静态的模型和历史数据进行训练并提供越策。很多时候用户的短期行为,对模型有修正作用,或者说对业务判断有预测作用。对系统来说,需要采集用户最近的行为并进行特征工程,然后给到实时机器学习系统进行机器学习。如果动态的实施新规则,或者推出新广告,就会很有参考价值。

2.实时计算流程

数仓建设,离线数仓,实时数仓,大数据

1)数据同步

​ 数据从Web平台中产生,通过数据同步系统导入到大数据平台,由于数据源不同,这里的数据同步系统实际上是多个相关系统的组合。数据库同步通常使用Sqoop、Kettle、nifi等,日志同步可以选择使用Flume等,不同的数据源产生的数据质量可能相差很大。数据库中产生的结构化数据,可以直接导入到大数据系统即可。但是日志和爬虫产生的半结构化和非结构化数据,都需要经过大量的清洗、转换处理才能有效的使用。

2)数据存储

​ 数据存储部分主要是对原始数据、清洗关联后的明细数据进行的存储操作,基于统一的实时数据模型分层理念,将数据依次存放至各层。以及将不同应用常见的数据可以分别存储在Kafka、HDFS、Kudu、Hive、ClickHouse、Hbase、ES中进行应用。

3)数据计算

​ 计算层主要使用Flink、Spark、Presto以及Clickhouse自带的计算能力等四种计算引擎,Flink计算引擎主要用于实时数据同步,流式ETL、关键系统秒级实时指标计算场景,Spark SQL主要用于复杂多维分析的准实时指标计算需求场景,Presto和ClickHouse主要满足多维自助分析、对查询响应时间要求不太高的场景。

4)实时应用

​ 以统一查询服务对各个业务数据场景进行支持,业务主要包括实时大屏、实时数据产品、实时OLAP、实时特征等。

当然一个好的大数据平台不能缺少元数据管理以及数据治理:

5)元数据指标管理

​ 主要对实时的Kafka表、kudu表、clickhouse表、hive表等进行统一管理,以数仓模型中表的命令方式规范表的命名,明确每张表的字段含义、使用方,指标管理则是尽量通过指标系统将所有的实时指标统一管理,明确计算口径,提供给不同的业务方使用;

6)数据质量及血缘分析

​ 数据质量分为平台监控和数据监控两个部分,血缘分析则是主要对实时数据依赖关系、实时任务的依赖关系进行分析。

以上列举的架构流程只是通用的数据模型,如果要具体的建设,需要考虑一下情况,业务需求需要实时还是准实时即可,数据时效性是妙计还是分钟级等。

  • 在调度开销方面,准实时数据是批处理过程,因此仍然需要调度系统支持,调度频率较高,而实时数据却没有调度开销;
  • 在业务灵活方面,因为准实时数据是基于ETL或OLAP引擎实现,灵活性优于流计算的方式;
  • 在对数据晚到的容忍度方面,因为准实时数据可以基于一个周期内的数据进行全量计算,因此对数据晚到的容忍度也是比较高的,而实时数据使用的是增量计算,对于数据晚到的容忍度更低一些;
  • 在适用场景方面,准实时数据主要用于有实时性要求但不太高、涉及多表关联和业务变更频繁的场景,如交易类型的实时分析,实时数据则更适用于要求高、数据量大的场景,如实施特征、流量实时分析等场景;

3.实时架构

​ 在某些场景中,数据的价值随着时间的推移而逐渐减少。所以在传统大数据离线数仓的基础上,逐渐对数据的实时性提出了更高的要求。

​ 于是随着诞生了大数据实时数仓,并衍生出两种架构Lamdba和Kappa。首先看一下两者简单的对比。

对比项 Lambda架构 Kappa架构
实时性 实时 实时
计算资源 批和流同时运行,资源开销大 只有流处理,仅针对新需求开发阶段运行两个作业,资源开销小
重新计算时吞吐 批式全量处理,吞吐较高 流式全量处理、吞吐较批处理低
开发、测试 每个需求都需要两套不同代码、开发、测试、上线难度较大 只需实现一套代码、开发、测试、上线难度相对较小
运维成本 维护两套系统(引擎)、运维成本大 只需维护一套系统、运维成本小
Lambda架构

数仓建设,离线数仓,实时数仓,大数据

​ Lambda架构,数据从底层的数据源开始,经过Kafka、Flume等数据组件进行收集,然后分成两条线进行计算:

  • 一条线是进入流式计算平台(例如Storm、Flink或者SparkStreaming),实时计算一些指标
  • 另一条线进入批量数据处理离线计算平台(例如Mapreduce、Hive、Spark SQL),计算T+1的相关业务指标,这些指标需要隔日才能看到

为什么Lambda架构要分成两条线计算?

​ 假设整个系统只有一个批处理层,会导致用户必须等待很久才能获取计算结果,一般有几个小时的延迟。电商数据分析部分只能查看前一天的统计分析结果,无法获取当前的结果,这对于实时决策来说有一个巨大的时间鸿沟,很可能导致管理者错过最佳的决策时机。

​ Lambda架构属于较早的一种架构方式,早期的流处理不如现在这样成熟,在准确性、扩展性和容错性上,流处理层无法直接取代批处理层,只能给用户提供一个近似结果,还不能给用户提供一个一致准确的结果。因此Lambda架构中,出现了批处理和流处理并存的现象。

在Lambda架构中,每层都有自己所肩负的任务。

1.批处理层存储管理主数据集(不可变的数据集)和预先批处理计算好的视图:

​ 批处理层使用可处理大量数据的分布式处理系统预先计算结果。它通过处理所有的已有历史数据来实现数据的准确性。这意味着它是基于完整的数据集来重新计算的,能够修复任何错误,然后更新现有的数据视图。输出通常存储在只读数据库中,更新则完全取代现有预先计算好的视图。

2.流处理层会实时处理新来的数据

​ 流处理层通过提供最新数据的实时视图来最小化延迟。流处理层所生成的数据视图可能不如批处理层最终生成的视图那样准确或完整,但他们几乎在收到数据后立即可用。而当同样的数据在批处理层处理完成后,在速度层的数据就可以被替代掉了。

那Lambda架构有没有缺点呢?

​ Lambda架构经理多年的发展,其优点是稳定,对于实时计算部分的计算成本可控,批量处理可以用晚上的时间来整体批量计算,这样把实时计算和离线计算高峰分开,这种架构支撑了数据行业的早期发展,但是它也有一些致命缺点,并在大数据3.0时代越来越不适应数据分析业务的需求。缺点如下:

  • *使用两套大数据处理引擎:*维护两个复杂的分布式系统,成本非常高。
  • *批量计算在计算窗口内无法完成:*在IOT时代,数据量级越来越大,经常发现夜间只有4、5个小时的时间窗口,已经无法完成白天20多个小时累计的数据,保证早上上班前准时出数据已经称为每个大数据团队头疼的问题。
  • *数据源变化都需要重新开发,开发周期长:*每次数据源的格式变化,业务的逻辑变化都需要针对ETL和Streaming开发修改,整体开发周期很长,业务反应不够迅速。

导致Lambda架构的缺点根本原因是要同时维护两套系统架构:批处理层和速度层。我们已经知道,在架构中加入批处理层是因为从批处理层得到的结果具有高准确性,而加入速度层是因为它在处理大规模数据时具有低延迟性。那我们能不能改进其中一层的架构,让它具有另外一层架构的特性呢?

​ 例如,改进批处理层的系统让它具有更低的延迟性,又或者改进速度层的系统,让它产生的视图更具准确性和更加接近历史数据呢?

​ 另外一种在大规模数据处理中常见的架构-Kappa加偶,便是在这样的思考下诞生的。

Kappa架构

​ Kafka创始人Jay Kreps认为在很多常见下,维护一套Lambda架构的大数据处理平台耗时耗力,于是提出在某些场景下,没有必要维护一个批处理层,直接使用一个流处理层即可满足需求,即下图所示的Kappa架构图:

数仓建设,离线数仓,实时数仓,大数据

​ Kappa架构只关注流式计算,数据以流的方式被采集过来,实时计算引擎将计算结果放入数据服务层以供查询。可以认为Kappa架构是Lambda架构的一个简化版本,只是去除掉了Lambda架构中的离线批处理部分;

​ Kappa架构的兴起主要又两个原因:

  • Kafka不仅起到消息队列的作用,也可以保存更长时间的历史数据,以替代Lambda架构中批处理层数据仓库部分。流处理引擎以一个更早的时间作为起点开始消费,起到批处理的作用。
  • Flink流处理引擎解决了事件乱序下计算结果的准确性问题。

Kappa架构相对更简单,实时性更好,所需的计算资源小于Lambda架构,随着实时处理的需求在不断增长,更多的企业开始使用Kappa架构。但这并不意味着Kappa架构能够取代Lambda架构。

​ Lambda和Kappa架构都有各自的适用领域:例如流处理与批处理分析流程比较统一,且允许一定的容错,用kappa架构比较合适,少量关键指标(例如交易金额、业绩统计等)使用Lambda架构进行批量计算,增加一次校对过程。

​ 还有一些比较复杂的场景,批处理与流处理产生不同的结果(使用不同的机器学习模型、专家系统,或者实时计算难以处理的复杂计算),可能更适合Lambda架构。

4.实时数仓解决方案

​ 实时数仓分层为了避免需求响应的烟囱式构建,实时数仓也引入了类似于离线数仓的的分层理念,主要为了提升模型的复用率,同时也要考虑模型的复用率,同时也要考虑易用性、一致性以及计算的成本。

​ 当然实时数仓的分层架构在设计上并不会像离线数仓那么复杂,避免数据在流转过程中造成的不必要的延迟相应。

数仓建设,离线数仓,实时数仓,大数据

1)ODS层

​ 以Kafka为支撑,将所有需要实时处理的相关数据放到Kafka队列中来实现贴源数据层;

2)DWD层

​ 实时计算订阅业务数据消息队列,然后通过数据清洗、多数据源join、流式数据于离线维度信息等组合,将一些相同粒度的业务系统、维度中的维度属性全部关联到一起,增加数据易用性和复用性,得到最终的实时明细数据;

3)DIM层

​ 存放用于关联查询的维度信息,可以根据数据现状来选择存储介质,例如使用HBase或者MySQL

4)DWS层

​ 轻度汇总层是为了便于面向ADHoc查询或者OLAP分析构建的轻度汇总结果集合,适合数据维度、指标信息比较多的情况,为了方便根据自定义条件的快速筛选和指标聚合,推荐使用MPP类型数据库进行存储,此层可视场景情况是否构建

5)APP层

​ 面向实时数据场景需求构建的高度汇总层,可以根据不同的数据应用场景决定使用存储介质或者引擎;例如面向业务历史明细、BI支持等OLAP分析场景,可以使用Durid、GreenPlum,面向实时监控大屏、高并发汇总指标等需求,可以使用KV模式的HBase;数据量较小的时候,也可以使用MySQL来进行存储。

这里需要注意的是:其实APP层已经脱离了数仓,这里虽然作为数仓的独立分层,但是实际APP层的数据已经分布存储在各种介质中用于使用。

基于Flink构建的实时数仓

​ 随着业务场景的丰富,更多的实时需求不断涌现,在追求实时任务高吞吐低延迟的同时,对计算过程中间状态管理,灵活时间窗口支持,以及exactly once语义保障的诉求也越来越多。

为什么选择Flink实时计算平台?之所以选择用Flink替代原有的Storm、SparkStreaming是基于以下原因考虑的,这也是实时数仓关注的核心问题:

  1. 高吞吐、低延迟;
  2. 端到端的Exactly-once,保证了数据的准确性;
  3. 可容错的状态管理,实时数仓里面会进行很多的聚合计算,这些都需要对于状态进行访问和管理;
  4. 丰富的API,对Streaming/Table/SQL支持良好,支持UDF、流式join、时间窗口等高级用法;
  5. 完善的生态体系,实时数仓的构建会涉及多种存储,Flink在这方面的支持也比较完善;

基于Flink的实时数仓数据转换过程:

​ 数据在实时数仓中的流转过程,实际和离线数仓非常相似,只是由Flink替代Hive作为了计算引擎,把存储由HDFS更换成了Kafka,但是模型的构建思路与流转并没有发生变化。

数仓建设,离线数仓,实时数仓,大数据

五、实时数仓建设核心

1.实时计算初期

​ 虽然实时计算在最近几年才火起来,但是在早期也有部分公司有实时计算的需求,但是数据量比较少,所以在实时方面行成不了完整的体系,基本所有的开发都是具体问题具体分析,来一个需求做一个,基本不考虑他们之间的关系,开发形式如下:

数仓建设,离线数仓,实时数仓,大数据

​ 如上如所示:拿到数据源后,会经过数据清洗,扩维,通过Flink进行业务逻辑处理,最后直接进行业务输出。把这个环节拆开来看,数据源端会重复引用相同的数据源,后面进行清洗、过滤、扩维等操作,都要重复做一遍,唯一不同的是业务的代码逻辑是不一样的。

​ 随着产品和业务人员对实时数据需求的不断增多,这种开发模式出现的问题越来越多:

  1. 数据指标越来越多,“烟囱式”的开发导致代码耦合问题严重。
  2. 需求越来越多,有的需要明细数据,有的需要OLAP分析。单一的开发模式难以应付多种需求
  3. 每个需求都要申请资源,导致资源成本急速膨胀,资源不能集约有效利用。
  4. 缺少完善的监控系统,无法在对业务产生影响之前发现并修复问题。

​ 大家看实时数仓的发展和出现的问题,和离线数仓非常相似,后期数据量大了之后产生各种各样的问题,离线数仓当时是怎么解决的呢?离线数仓通过分层架构使数据解耦,多个业务系统可以共用数据,实时数仓是否也可以用到分层架构呢?当前是可以的,但是细节上和离线的分层还是会有稍微的不同。

2.实时数仓建设

​ 从方法论来讲,实时和离线是非常相似的,离线数仓早期的时候也是具体问题具体分析,当数据规模涨到一定量的时候才会考虑如何治理。分层是一种非常有效的数据治理方式,所以在实时数仓如何进行管理的问题上,首先考虑的也是分层的处理逻辑。

数仓建设,离线数仓,实时数仓,大数据

实时数仓各层次作用:

  • 数据源:在数据源的层面,离线和实时在数据源是一致的,主要分为日志类和业务类,日志类又包括用户日志,埋点日志以及服务器日志等。
  • **实时明细层:**在明细层,为了解决重复建设的问题,要进行统一构建,利用离线数仓的模式,建设统一的基础明细数据层,按照主题进行管理,明细层的目的是给下游提供直接可用的数据,因此要对基础层进行统一的加工,比图清洗、过滤、扩维等。
  • **汇总层:**汇总层通过Flink的简洁算子直接算出结果,并且形成汇总指标池,所有的指标都统一在汇总层加工,所有人按照统一的规范管理建设,形成可复用的汇总结果。

从这可以看出,实时数仓和离线数仓的分层非常相似,比如 数据源层,明细层,汇总层,以及应用层,两者的命名的模式可能都是一样的。但是自己研究的话,会发现两者还是又很多的区别,比如:

  • 与离线数仓相比,实时数仓的层次更少一些:
    • 从目前建设数仓的经验来看,数仓的数据明细层内容会非常丰富,处理明细数据外一般还会包含轻度汇总层的概念,另外离线数仓中应用层数据在数仓内部,但是实时数仓中,app应用层已经落入应用系统的存储介质中,可以把该层与数仓的表分离。
    • 应用层少建设的好处:实时处理数据的时候,每建一个层次,数据必然会产生一定的延迟。
    • 汇总层少见的好处:在汇总统计的时候,往往为了零容忍一部分数据的言辞,可能会人为的制造一些延迟来保证数据的准确。举例:在统计跨天相关的订单事件中的数据,可能会等到00:00:05或者00:00:10再统计,确保00:00前的数据已经全部接收到位,再进行统计。所以汇总层的层次太多的话,就会更大的加重认为造成的数据延迟。
  • 与离线数仓相比,实时数仓的数据源存储不同:
    • 在建设离线数仓的时候,基本整个离线数仓都是建立在Hive表之上。但是,在建设实时数仓的时候,同一份表,会使用不同的方式进行存储。比如常见的情况下,明细数据或者汇总数据都会存在kafka里面,但是像城市、渠道等维度信息需要借助Hbase,MySQL或者其他KV存储等数据库来进行存储。

3.Lambda架构的实时数仓

数仓建设,离线数仓,实时数仓,大数据

​ Lambda架构是比较经典的架构,以前实时的场景不是很多,以离线为主,当附加了实时场景后,由于离线和实时的时效性不同,导致技术生态是不一样的。Lambda架构相当于附加了一条实时生产链路,在应用层进行一个整合,双路生产,各自独立。这在业务应用中也是顺理成章采用的一种方式。

​ 双路生产会存在一些问题,比如加工逻辑double,开发运维也会double,资源同样会变成两个资源链路。因为存在以上问题,所以又演进了一个Kappa架构。

4.Kappa架构的实时数仓

数仓建设,离线数仓,实时数仓,大数据

​ Kappa架构从架构涉及来讲比较简单,生产统一,一套逻辑同时生产离线和实时。但是在实际应用场景中有比较大的局限性,因为实时数据的同一份表,会使用不同的方式存储,这就导致关联时需要跨数据源,操作数据又很大的局限性,所以在业内直接使用Kappa架构生产落地的案例不多见,且场景比较单一。

​ 关于Kappa架构,熟悉实时数仓生产的同学,可能会有一个疑问。因为我们呢经常会面临业务变更,所以很多业务逻辑是需要迭代的。之前产出的一些数据,如果口径变更了,就需要重算,甚至重刷历史数据。对于实时数仓来说,怎么去解决数据重算问题?

​ kappa架构在这一块的思路是:首先要准备号一个能存储历史数据的消息队列,比如Kafka,并且这个消息队列是可以支持你从某个历史的节点重新开始消费的。接着需要重新起一个任务,从原来比较早的一个时间节点去消费Kafka上的数据,然后当这个新的任务运行的进度已经能够和现在的正在跑的任务齐平的时候,你就可以把现在任务的下游切换到新的任务上面,旧的任务就可以停掉,并且原来产出的表也可以被删掉。

5.流批结合的实时数仓

​ 随着实时OLAP技术的发展,目前开源的OLAP引擎在性能上,易用性方面有了很大的提升,如Doris、Presto等,加上数据库技术的迅速发展,使得流批结合的方式变得简单。

数仓建设,离线数仓,实时数仓,大数据

​ 数据从日志统一采集到消息队列,再到实时数仓,作为基础数据流的建设是统一的。之后对于日志类实时特征,实时大屏类应用走实时流计算。对于Binlog类业务分析走实时OLAP批处理。

​ 我们看到流批结合的方式与上面几种架构的存储方式发生了变化,由Kafka换成了Iceberg,Iceberg是介于上层计算引擎和底层存储格式之间的一个中间层,我们可以把他定义成一种数据组织格式,底层存储还是HDFS,那么为什么加了中间层,就对流批结合处理的比较号了呢?Iceberg的ACID能力可以简化整个流水线的设计,降低整个流水线的延迟,并且所具有的修改、删除能力能够有效的降低开销,提升效率。Iceberg可以有效支持批处理的高吞吐数据扫描和流计算按分区粒度并发实时处理。

六、数据治理

​ 数据建设真正的难点不在于数仓设计,而在于后续业务发展起来,业务线变得庞大之后的数据治理,包括资产治理数据质量监控数据指标体系的建设等。

​ 数据治理的范围很广,包含数据本身的管理、数据安全、数据质量、数据成本等。在DAMA数据管理知识体系指南中,数据治理位于数据管理车轮图的正中央,是数据架构、数据建模、数据存储、数据安全、数据质量、元数据管理、主数据管理等十大数据管理领域的总纲,为各项数据管理活动提供总体指导策略。

数仓建设,离线数仓,实时数仓,大数据

1.数据治理之道是什么

1)数据治理需要体系建设

​ 为发挥数据价值需要三个要求:合理的平台架构完善的治理服务体系化的运营手段

​ 根据企业的规模、所属行业、数据量等情况选择合适的平台架构;治理服务需要贯穿数据全生命周期,保证数据在采集、加工、共享、存储、应用整个过程中的,完整性、准确性、一致性和实效性;运营手段应当包括规范的优化、组织的优化以及流程的优化等等方面。

2)数据治理需要夯实基础

​ 数据治理需要循序渐进,但在建设初期至少需要关注三个方面:数据规范数据质量数据安全。规范化的模型管理是保障数据可以被治理的前提条件,高质量的数据是数据可用的前提条件,数据的安全管控是数据可以共享交换的前提条件。

3)数据治理需要IT赋能

​ 数据治理不是一堆规范文档的堆砌,而是需要将治理过程中所产生的规范、流程、标准落地到IT平台上,在数据生产中通过以终为始前想的方式进行数据治理,避免事后稽核带来各种被动和运维成本的增加。

4)数据治理需要聚焦数据

​ 数据治理的本质是管理数据,因此需要加强元数据管理和主数据管理,从源头治理数据,补齐数据的相关属性和信息,比如:元数据、质量、安全、业务逻辑、血缘等,通过元数据驱动的方式管理数据生产、加工和使用。

5)数据治理需要建管一体化

​ 数据模型血缘与任务调度一致性是建管一体化的关键,有助于解决数据管理与数据生产口径不一致的问题,避免出现两张皮的低效管理模式。

2.浅谈数据治理方式

​ 如上所说,数据治理的范围非常广,其中最重要的是数据质量治理,而数据质量涉及的范围也很广,贯穿数仓的整个生命周期,从数据产生->数据接入->数据存储->数据处理->数据输出->数据展示,每个阶段都需要质量治理,评价维度包括完整性、规范性、一致性、准确性、唯一性、关联性等。

​ 在系统建设的各个阶段都应该根据标准进行数据质量检测和规范,及时进行治理,避免事后的清洗工作。

​ 质量检测可参考以下标准:

维度 衡量标准
完整性 业务指定必须的数据是否确实,不允许有空字符或者空值等。例如,数据源是否完整、维度取值是否完整、数据取值是否完整等。
时效性 当需要使用时,数据能否反应当前事实。即数据必须及时,能够满足系统对数据时间的要求。例如处理(获取、整理、清洗、加载等)的及时性
唯一性 在指定的数据集中数据值是否唯一
参考完整性 在指定的数据集中数据值是否唯一
依赖一致性 数据项取值是否满足与其他数据项之间的依赖管理
正确性 数据内容和定义是否一致
精确性 数据精度是都达到业务规划要求的位数
技术有效性 数据项是否按已定义的格式标准组织
业务有效性 数据项是否符合已定义的
可信度 根据客户调查或客户主动提供获得
可用性 数据可用的时间和数据需要被访问时间的比例
可访问性 数据是否便于自动化读取

下面是根据美团的技术文章总结的几点具体治理方式:

1)规范治理

​ 规范是数仓建设的保障。为了避免出现指标重复建设和数据质量差的情况,统一按照最详细、可落地的方法进行规范建设。

1.1)词根

​ 词根是维度和指标管理的基础,划分为普通词根与专有词根,提高词根的易用性和关联性。

  • 普通词根:描述事务的最小单位,如:交易-trade
  • 专有词根:具备约定成俗或行业专属的描述题,如:美元-USD

1.2)表命名规范

通用规范

  • 表名、字段名采用一个下划线分割词根(示例:clienttype -> client_type)
  • 每部分使用小写英文单词,属于通用字段的必须满足通用字段信息的定义
  • 表名、字段名需以字母开头
  • 表名、字段名最长不超过64个英文字符
  • 优先使用词根中已有关键字(数仓标准配置中的词根管理),定期review新增命名的不合理性
  • 在表名自定义部分禁止采用非标准的缩写

表命名规则

  • 表名称 = 类型 + 业务主题 + 子主题 + 表含义 + 存储格式 + 更新频率 + 结尾

1.3)指标命名规范

结合指标的特性以及词根管理规范,将指标进行结构化处理。

1.基础指标词根,即所有指标必须包含以下基础词根:

基础指标词根 英文全称 Hive数据类型 MySQL数据类型 长度 精度 词根 样例
数量 count Bigint Bigint 10 0 cnt
金额类 amount Decimal Decimal 20 4 amt
比率/占比 ratio Decimal Decimal 10 4 ratio 3.1416

2.业务修饰词,用于描述业务场景的词汇,例如trade-交易

3.日期修饰词,用于修饰业务发生的时间区间

日期类型 全称 词根 备注
daily d
weekly w

4.聚合修饰词,对结果进行聚集操作

聚合类型 全称 词根 备注
平均 average avg
周累计 wtd wtd 本周一截止到当前累计

5.基础指标,单一的业务修饰词+基础指标词根构建基础指标,例如:交易金额-trade_amt

6.派生指标,多修饰词+基础指标词根构建派生指标。派生指标继承基础指标的特性,例如:安装门店数量-install_poi_cnt

7.普通指标命名规范,与字段命名规范一致,由词汇转换即可

数仓建设,离线数仓,实时数仓,大数据

2)架构治理

2.1)数据分层

​ 优秀可靠的数仓体系,往往需要清晰的数据分层结构,即要保证数据层的稳定又要屏蔽对下游的影响,并且要避免链路过长,一般的分层架构如下:

数仓建设,离线数仓,实时数仓,大数据

2.2)数据流向

​ 稳定业务按照标准的数据流向进行开发,即ODS->DWD->DWA->APP。非稳定业务或探索性需求,可以遵循ODS->DWD->APP或者ODS->DWD-DWT->APP两个模型数据流。在保障了数据链路的合理性之后,又在此基础上确认模型分层引用原则:

  • 正常流向:ODS->DWD->DWT->DWA->APP,当出现ODS->DWD->DWA->APP这种关系时,说明主题域未覆盖全。应将DWD数据落地到DWT中,对于使用频度非常低的表允许DWD->DWA。
  • 尽量避免出现DWA宽表中使用DWD又使用(该DWD所属主题域)DWT的表。
  • 同一主题域内对DWT生成DWT的表,原则上尽量避免,否则会影响ETL的效率。
  • DWT、DWA和APP中禁止直接使用ODS的表,ODS的表只能被DWD引用。
  • 禁止出现反向依赖,例如DWT的表依赖DWA的表。

3)元数据治理

元数据可以分为技术元数据和业务元数据:

技术元数据为开发和管理数据仓库的IT人员使用,它描述了与数据仓库开发、管理和维护相关的数据,包括数据源信息、数据转换描述、数据仓库模型、数据清洗与更新规则、数据映射和访问权限等。

常见的技术元数据有:

  • 存储元数据:如表、字段、分区等信息。
  • 运行元数据:如大数据平台上所有作业运行等信息:类似于Hive Job日志,包括作业类型、实例名称、输入输出、SQL、运行参数、执行时间,执行引擎。
  • 数据开发平台中数据同步、计算任务、任务调度等信息:包括数据同步输入输出表和字段,以及同步任务本身的节点信息:计算任务主要有输入输出、任务本身的节点信息任务调度主要有任务的依赖类型、依赖关系等,以及不同类型调度任务的运行日志等。
  • 数据质量和运维相关元数据:如任务监控、运维报警、数据质量、故障等信息,包括任务监控运行日志、告警配置及运行日志、故障信息等。

业务元数据为管理层和业务分析人员服务,从业务角度描述数据,包括商务术语、数据仓库中有什么数据、数据的位置和数据的可用性等,帮助业务人员更好的理解数据仓库中哪些数据是可用的以及如何使用。

  • 常见的业务元数据有维度及属性(包括维度编码、字段类型、创建人、创建时间、状态等)、业务过程、指标(包括指标名称、指标编码、业务口径、指标类型、责任人、创建时间、状态、SQL等)、安全等级、计算逻辑等规范化定义,用于更好的管理和使用数据。数据应用元数据,如数据报表、数据产品等的配置和运行元数据。

元数据不仅定义了数据仓库中数据的模式、来源、抽取和转换规则等,而且是整个数据仓库系统运行的基础,元数据把数据仓库系统中各个松散的组件联系起来,组成一个有机的整体。

元数据治理主要解决三个问题:

  1. 通过建立相应的组织、流程和工具,推动业务标准的落地实施,实现指标的规范定义,消除指标认知的歧义;
  2. 基于业务现状和未来的演进方式,对业务模型进行抽象,指定清洗的主题、业务过程和分析方向,构建完备的技术元数据,对物理模型进行准确完善的描述,并打通技术元数据与业务元数据的关系,对物理模型进行完备的刻画;
  3. 通过元数据建设,为使用数据提效,解决“找数、理解数、评估"难题以及"取数、数据可视化"等难题;

4)安全治理

​ 围绕数据安全标准,首先要有数据的分级、分类标准,确保数据在上线前有着准确的密级。第二,针对数据使用方,要有明确的角色授权标准,通过分级分类和角色授权,来保障重要数据拿不走。第三,针对敏感数据,要有隐私管理标砖,保障敏感数据的安全存储,即使未授权用户绕过权限管理拿到敏感数据,也要确保其看不懂。第四,通过指定审计标准,为后续的审计提供审计依据,确保数据走不脱。

5)数据生命周期治理

​ 任何事物都具有一定的生命周期,数据也不例外。从数据的产生、加工、使用乃至消亡都应该有一个科学的管理方法,将极少或者不再使用的数据从系统中剥离出来,并通过核实的存储设备进行保留,不仅能够提高系统的运行效率,更好的服务客户,还能大幅度减少因为数据长期保存带来的存储成本。数据生命周期一般包含在线阶段、归档阶段(有时还会进一步划分在线归档阶段和离线归档阶段)、销毁阶段三大阶段,管理内容包括建立合理的数据类别,针对不同类别的数据指定各个阶段的保留时间、存储介质、清理规则和方式、注意事项等。

数仓建设,离线数仓,实时数仓,大数据

从上图数据生命周期中个参数间的关系中我们可以了解到,数据生命周期管理可以使得高价值数据的查询效率大幅提升,而且高价格的存储介质的采购量也可以减少很多;但是随着数据的使用程度下降,数据被逐渐归档,查询时间也慢慢的变长;最后随着数据的使用频率和价值基本没有了之后,就可以逐渐销毁了。

七、数据质量建设

​ 数据治理的范围非常广,包含数据本身的管理、数据安全、数据质量、数据成本。在这么多治理内容中,大家觉得最重要的治理是什么?当然是数据质量治理,因为数据质量是数据分析结论有效性和准确性的基础,也是这一切的前提,所以如何保障数据质量,确保数据可用性是数据仓库建设中不容忽视的环节。

数仓建设,离线数仓,实时数仓,大数据

​ 数据质量涉及的范围很广,贯穿数仓的整个生命周期,从数据产生->数据接入->数据存储->数据处理->数据输出->数据展示,每个阶段都需要质量治理。在系统建设的各个阶段都应该根据标准进行数据质量检测和规范,及时进行治理,避免时候的清洗工作。

1.为什么要进行数据质量评估

很多刚入门的数据相关工作者,拿到数据后会立刻开始对数据进行各种探查、统计分析等,企图能立即发现数据背后隐藏的信息和知识。然后忙活后,会发现并不能提炼太多有价值的信息,白白浪费大量的时间和精力。比如和数据打交道的过程中,可能会出现以下的场景:

**场景一:**作为数据分析人员,要统计一下近7天用户的购买情况,结果从数仓中统计发现,很多数据发生了重复记录,甚至有些数据统计单位不统一。

**场景二:**业务看报表,发现某一天的的成交gmv暴跌,经过排查发现,是当天的数据缺失。

造成这种情况的一个重要因素是忽视了对数据质量的客观评估,没有制定合理的衡量标准,导致没有发现数据已出现问题。所以,进行科学、客观的数据质量衡量标准是非常必要且十分重要的。

2.数据质量衡量标准

如何评估数据质量的好坏,业界有不同的标准,主要可以从以下六个维度进行评估:包括完整性规范性一致性准确性唯一性及时性

数仓建设,离线数仓,实时数仓,大数据

1)数据完整性

完整性指的是数据信息是否存在缺失的状况,数据缺失的情况可能是整个数据记录缺失,也可能是数据中某个字段信息的记录缺失。

2)数据规范性

规范性指的是描述数据遵循预定的语法规则的程度,是否符合其定义,比如数据的类型、格式、取值范围等。

3)数据一致性

一致性是指数据是否遵循了统一的规范,数据集合是否保持了统一的格式。数据质量的一致性主要体现在数据记录的规范和数据是否符合逻辑,一致性并不意味着数值上的绝对相同,而是数据收集、处理的方法和标准一直。常见的一致性指标有:ID 重合度、属性一致、取值一致、采集方法一致、转换步骤一致。

4)数据准确性

准确性是指数据记录的信息是否存在异常或错误。和一致性不一样,存在准确性问题不仅仅只是规则上的不一致,更常见的数据准确性错误就如乱码,其次异常的大或者小的数据也是不符合条件的数据。常见的准确性指标有:缺失值占比、错误值占比、异常值占比、抽样偏差、数据噪声。

5)数据唯一性

唯一性指的是数据库的数据不存在重复的情形。比如真是成交一万条,但是数据表重复就有3000条了,成了1.3万条成交记录,这种数据不符合数据唯一性。

6)数据及时性

及时性是指数据从产生到可以查看的时间间隔,也叫数据的延长时长。比如一份数据是统计离线今日的,结果都是第二天甚至第三天才能统计完,这种数据不符合数据及时性。

还有一些其他的衡量标准

维度 衡量标准
参照完整性 数据项是否在父表重有定义
依赖一致性 数据项取值是否满足与其他数据项之间的依赖关系
正确性 数据内容和定义是否一致
精确性 数据精度是否按已定义的格式标准组织
技术有效性 数据项是否按已定义的格式标准组织
业务有效性 数据项是否符合已定义的
可信度 根据客户调查或客户主动提供获得
可用性 数据可用的时间和数据需要被访问的比例
可访问性 数据是否便于自动化读取

3.数据质量管理流程

数仓建设,离线数仓,实时数仓,大数据

1)数据资产等级

1.1)等级定义

根据当前数据质量不满足完整性、规范性、一致性、准确性、唯一性、及时性,对业务的影响程度大小来划分数据的资产等级。

  1. 毁灭性:数据一旦出错,会引起巨大的资产损失,面临重大收益受损等。标记为L1
  2. 全局性:数据用于集团业务、企业级效果评估和重要决策任务等。标记为L2
  3. 局部性:数据用于某个业务线的日常运营、分析报告等,如果出现问题会给该业务线造成一定的影响或影响其工作效率。标记为L3
  4. 一般性:数据用于日常分析,出现问题的带来的影响很小。标记为L4

重要程度:L1>L2>L3>L4>Lx。如果一份数据出现多个应用常见重,则根据其最重要程度进行标记。

1.2)等级划分

定义数据资产登基后,我们可以从数据流程链路开始进行数据资产等级标记,完成数据资产等级确认,给不同的数据定义不同的重要程度。

1.分析数据链路:

数据是从业务系统重产生的,经过同步工具进入数据仓库系统中,在数据仓库中进行一般意义上的清洗、加工、整合、算法、模型等一系列运算后,再通过同步工具输出到数据产品中进行消费。而从业务系统到数据仓库再到数据产品都是以表的形式体现,其流转过程如下图所示:

数仓建设,离线数仓,实时数仓,大数据

2.标记数据资产等级:

在所有数据链路,整理出消费各个表的应用业务。通过给这些应用划分数据资产等级,结合数据的上下游依赖关系,将整个链路打上某一类资产等级标签。

举例:

​ 假如公司有统一的订单服务中心。应用层的应用业务是按照业务线,商品类型和地域统计公司的订单数量和订单金额,命名为order_num_amount。

​ 假设该应用会影响到整个企业的重要业务决策,我们可以把应用定级为L2,从而整个数据链路上的表的数据等级,都可以标记为L2-order_num_amount,一直标记到源数据业务系统,如下图所示:

数仓建设,离线数仓,实时数仓,大数据

2)数据加工过程卡点校验

2.1)在线系统数据校验

​ 在线业务复杂多变,总是在不断的变更,每一次变更都会带来数据的变化,数据仓库需要适应多变的业务发展,及时做到数据的准确性。

​ 基于此,在线业务的变更如何高效的通知到离线数仓,同样也是需要考虑问题。为了保障在线数据和离线数据的一致性,我们可以通过工具+人员管理并行的方法来尽可能的解决以上问题:即要在工具上自动捕捉每一次业务的变化,同时也要求开发人员在意识上自动进行业务变更通知。

  1. 业务上线发布平台

    监控业务上线发布平台上的重大业务变更,通过订阅发布过程,及时将变更内容通知到数据部分。由于业务复杂多变,日常发布变更频繁,每次都要通知数据部分,会造成资源浪费。这是,可以使用之前已经完成标记的数据资产等级标签,针对涉及高等级数据应用的数据资产,整理出哪些类型的业务变更会影响到数据的加工或者影响数据统计口径的调整,则这些情况都必须通知到数据部门。如果公司没有自己的业务发布平台,那么就需要与业务部分约定好,针对高等级的数据资产的业务变更,需要以邮件或者其他书面的说明及时反馈到数据部门。

  2. 操作人员管理

    工具只是辅助建管的一种手段,而使用工具的人员才是核心。数据资产等级的上下游打通过程需要通知给在线业务系统开发人员,使其知道哪些是重要的核心数据资产,哪些暂时还只是作为内部分析数据使用,提高在线开发人员的数据风险意识。

    可以通过培训的方式,把数据质量管理的诉求,数据质量管理的整个数据加工过程,以及数据产品的应用方式及应用场景告知在线开发人员,使其了解数据的重要性、价值及风险。确保在线开发人员在完成业务目标的同时,也要考虑数据的目标,保持业务端和数据端一致。

2.2)离线系统数据校验

​ 数据从在线业务系统到数据仓库再到数据产品的过程,需要在数据仓库这一层完成数据的清洗、加工。正是有了数据的加工,才有了数据仓库模型和数据仓库代码的建设。如何保障数据加过程中的质量,是离线数据仓库保障数据质量的一个重要环节。

​ 在这些环节中,我们可以采用以下方式来保障数据质量:

  • 1.代码提交核查

    开发相关的规则引擎,辅助代码提交校验。规则分类大致为:

    • 代码规范类规则:

      表命名规范、字段命名规范、生命周期设置、表注释等。

    • 代码质量类规则:

      如分母为0提醒,NULL值参与计算提醒等

    • 代码性能类规则:

      如大表提醒、重复计算检测、大小表join操作提醒等

  • 2.代码发布核查

    加强测试环节,测试环节测试后再发布到生成环境,且生成环境测试通过后才算发布成功。

  • 3.任务变更或重跑数据

    在进行数据更新操作前,需要通知下游数据变更原因、表更逻辑、变更时间等信息。下游没有异议后,再按约定时间执行变更发布操作。

3)数据处理风险

​ 风险点监控主要是针对数据在日常运行过程中出现的风险进行监控并设置报警机制,主要包括在线数据和离线数据运行风险点监控。

3.1)数据质量监控

在线业务系统的数据生产过程需要保证数据质量,主要根据业务规则对数据进行监控。

​ 比如交易系统配置的一些监控规则,如订单拍下时间、订单完结时间、订单支付金额、订单状态流转等配置校验规则。订单拍下时间肯定不会大于当天时间,也不会小于上线时间,一旦出现异常的订单创建时间,就会立即报警,同时报警给多人。通过这种机制,可以及时发现并解决问题。

​ 随着业务负责程度的提升,会导致规则繁多、规则配置的运行成本增大,这时可以按照我们之前的数据资产等级有针对性的监控。

离线数据风险点监控主要包括对数据准确性和数据产出及时性的监控。对数据调度平台上所有数据处理调度进行监控。

3.2)数据及时性监控

​ 在确保准确性的前提下,需要进一步让数据能够及时提供服务,否则数据的价值将大幅度降低,甚至没有价值,所以确保数据及时性也是保障数据质量重要的环节之一:

  • 1.任务优先级

    在优先级的设置上,要先确定业务的资产等级,等级越高的业务对应的消费节点越高,优先调度并占用计算资源,确保高等级业务的准时产出。总之,就是按照数据资产等级优先执行高等级数据资产的调度任务,优先级保障高等级业务的数据需求。

  • 2.任务报警

    任务报警和优先级类似,在任务执行中,可能出错或者延迟,为了保障最重要数据产出,需要立即处理出错并介入处理延迟。

4.小结

​ 想要真正解决数据质量问题,就要明确业务需求并从需求开始控制数据质量,并建立数据质量管理机制。从业务出发做问题定义,由工具自动、及时发现问题,明确问题负责人,通过邮件、短信等方式进行通知,保证问题及时通知到负责人。跟踪问题整改进度,保证数据质量问题全过程的管理。

八、数仓规范建设指南

1.数仓公共开发规范

1)层次调用规范

​ 稳定业务按照标准的数据流向进行开发,即ODS -> DWD -> DWS -> APP。非稳定业务或探索型业务,可以遵循ODS -> DWD -> APP或者ODS -> DWD -> DWM -> APP等模型。

在保障数据链路合理性后,也必须保证模型分层引用原则:

  • 正常流向:ODS -> DWD -> DWM -> DWS -> APP,当出现ODS -> DWD -> DWS -> APP这种关系时,说明主题域未覆盖全,应将DWD数据落到DWM中,对于使用频度非常低的表允许DWD -> DWS
  • 尽量避免出现DWS宽表中使用DWD又使用DWM的表
  • 同一主题域内对DWM生成DWM的表,原则上要尽量避免,否则会影响ETL效率
  • DWM、DWS和APP中禁止使用ODS的表,ODS的表只能被DWD引用
  • 禁止出现反向依赖,例如DWM的表依赖DWS的表。

2)数据类型规范

​ 需统一规定不同的数据的数据类型,严格按照规定的数据类型执行

  • 1.金额:double类型或使用decimal(11,2)控制精度等,明确单位是分还是元
  • 2.字符串:string类型或者text类型
  • 3.id类型:bigint
  • 4.时间:string类型或者text类型
  • 5.状态:string类型或者text类型

3)数据冗余规范

​ 宽表的冗余字段要确保:

  • 1.冗余字段要使用高频,下游3个或以上使用
  • 2.冗余字段引入不应造成本身数据产生过多的延后
  • 3.冗余字段和已有字段的重复率不应过大,原则上不应超过60%,如需要可以选择join或原表拓展

4)NULL字段处理规范

  • 对于维度字段,需设置为-1
  • 对于指标字段,需设置为0

5)指标口径规范

​ 保证主题域内,指标口径一直,无歧义

​ 通过数据分层,提供统一的数据出口,统一对外输出的数据口径,避免同一指标不同口径的情况。

5.1)指标梳理

​ 指标口径的不一致使得数据使用的成本极高,经常出现口径打架、反复核对数据的问题。在数据治理中,我们将需要梳理到的所有指标进行进一步的梳理,明确其口径,如果存在两个指标名称相同,但口径不一致,先判断是否进行合并,如需要同时存在,那么在命名上必须能够区分开。

5.2) 指标管理

​ 指标管理分为原子指标维护和派生指标维护

原子指标:

  • 选择原子指标的归属产线、业务模板、数据域、业务过程
  • 选择原子指标的统计数据来源于该业务过程下的原始数据源
  • 录入原子指标的英文名称、中文名称、概述
  • 填写指标函数
  • 系统根据指标函数自动生成原子指标的定义表达式
  • 系统根据指标定义表达式以及数据源表生成原子指标SQL

派生指标:

  • 在原子指标的基础上选择一些维度或者修饰限定词

6)数据表处理规范

6.1) 增量表

新增数据,增量数据是上次导出之后的新数据

  • 1.记录每次增加的量,而不是总量
  • 2.增量表,只报变化量,无变化不用报
  • 3.每天一个分区

6.2)全量表

每天的所有的最新状态的数据

  • 1.全量表,有无变化,都要报
  • 2.每次上报的数据都是所有的数据(变化的+没有变化的)
  • 3.只有一个分区

6.3)快照表

按日分区,记录截止数据日期的全量数据

  • 1.快照表,有无变化,都要报
  • 2.每次上报的数据都是所有的数据(变化的+没有变化的)
  • 3.一天一个分区

6.4)拉链表

记录截止日期的全量数据

  • 1.记录一个事务从开始,一直到当前的所有变化的信息
  • 2.拉链表每次上报都是历史记录的最终状态,是记录在当前时刻的历史总量
  • 3.当前记录存的是当前时间之前的所有历史记录的最后变化量(总量)
  • 4.只有一个分区

7)表的生命周期管理

这部分主要是通过对历史数据的等级划分与对表类型的划分生成响应的生命周期管理矩阵。

7.1)历史数据等级划分

主要将历史数据划分P0、P1、P2、P3四个等级,其具体定义如下:

  • P0:非常重要的主题域数据和非常重要的应用数据,具有不可恢复性,如交易、日志、集团KPI数据、IPO关联表。
  • P1:重要的业务数据和重要的应用数据,具有不可恢复性,如重要的业务产品数据
  • P2:重要的业务数据和重要的应用数据,具有可恢复性,如交易线ETL产生的中间过程数据
  • P3:不重要的业务数据和不重要的应用数据,具有可恢复性,如某些SNS产品报表

7.2)表类型划分

  • 1.事件型流水表(增量表)

    事件型流水表(增量表)指数据无重复或者无主键数据,如日志

  • 2.事件型镜像表(增量表)

    事件型镜像表指业务过程性数据,有主键,但是对于同样主键的属性会发生缓慢变化,如交易、订单状态与时间会根据业务发生变更。

  • 3.维表

    维表包括维度与维度属性数据,如用户表、商品表

  • 4.Merge 全量表

    Merge全量表包括业务过程性数据或者维表数据。由于数据本身有新增的或者发生状态变更,对于同样主键的数据可能会多保留一份,因此可以对这些数据根据主键进行Merge操作,主键对应的属性只会保留最新状态,历史状态保留在前一天分区中。例如,用户表、交易表都可以进行Merge操作

  • 5.ETL临时表

    ETL临时表是指ETL处理过程中产生的临时表数据,一般不建议保留,最多7天。

  • 6.普通全量表

    很多小业务数据或者产品数据,BI一般是直接全量拉取,这种方式效率快,对存储压力也不是很大,而且表保留时间长,可以根据历史数据等级确定保留策略。

通过上述历史数据等级划分与表类型划分,生成相应的生命周期矩阵,如下图所示:

数仓建设,离线数仓,实时数仓,大数据

2.数仓各层开发规范

1)ODS层设计规范

同步规范:

  • 一个系统源表只允许同步一次
  • 全量表初始化同步和增量表同步处理逻辑要清晰
  • 以统计日期和时间进行分区存储
  • 目标表字段在源表不存在时要自动填充处理

表分类与生命周期:

  • 1.ods流水全量表
    • 不可再生的永久保存
    • 日志可按留存要求
    • 按需设置保留特殊日期数据
    • 按需设置保留特殊月份数据
  • 2.ods镜像型全量表:
    • 推荐按天存储
    • 对历史变化进行保留
    • 最新数据存储在最大分区
    • 历史数据按需保留
  • 3.ods增量数据
    • 推荐按天存储
    • 有对应全量表,建议只保留14天数据
    • 无对应全量表的,永久保留
  • 4.ods的etl过程中的临时表
    • 推荐按需保留
    • 最多保留7天
    • 建议用完即删,下次使用再生成
  • 5.DBSync非去重数据
    • 通过中间层保留,默认用完即删,不建议保留

数据质量:

  • 全量表必须配置唯一性字段标识
  • 对分区空数据进行监控
  • 对枚举类型字段,进行枚举值变化和分布监控
  • ods表数据量级和记录数做环比监控
  • ods全表都必须要有注释

2)公共维度层设计规范

2.1)设计准则

  • 1.一致性

    公共维度在不同的物理表中的字段名称、数据类型、数据内容必须保持一致(历史原因导致不一致,要做好版本控制)

  • 2.维度的组合与拆分

    • 组合原则:

      将将维度与关联性强的字段进行组合,一起查询,一起展示,两个维度必须具有天然的关系,如:商品的基本属性和所属品牌

      无相关性:如一些使用频率较小的杂项维度,可以构建一个集合杂项维度的特殊属性。

      行为维度:经过计算的度量,但下游当维度处理,例:点击量0-1000,100-1000等,可以做聚合分类

    • 拆分与冗余:

      针对重要性,业务相关性、源、使用频率等可以分为核心表、扩展表

      数据记录较大的维度,可以使用冗余一些子集

2.2)存储及生命周期管理

建议按天分区

  • 3个月内最大访问跨度<=4天时,建议保留最近7天分区;
  • 3个月内最大访问跨度<=12天时,建议保留最近15天分区;
  • 3个月内最大访问跨度<=30天时,建议保留最近33天分区;
  • 3个月内最大访问跨度<=90天时,建议保留最近120天分区;
  • 3个月内最大访问跨度<=180天时,建议保留最近240天分区;
  • 3个月内最大访问跨度<=300天时,建议保留最近400天分区;

3)DWD明细层设计规范

3.1)存储及生命周期管理

建议按天分区

  • 3个月内最大访问跨度<=4天时,建议保留最近7天分区;
  • 3个月内最大访问跨度<=12天时,建议保留最近15天分区;
  • 3个月内最大访问跨度<=30天时,建议保留最近33天分区;
  • 3个月内最大访问跨度<=90天时,建议保留最近120天分区;
  • 3个月内最大访问跨度<=180天时,建议保留最近240天分区;
  • 3个月内最大访问跨度<=300天时,建议保留最近400天分区;

3.2)事务型事实设计准则

  • 基于数据应用需求分析设计事务性事实表,结合下游较大的针对某个业务过程和分析指标需求,可考虑基于某个事件过程构建事务型事实表
  • 一般选用事件的发生日期或事件作为分区字段,便于扫描和裁剪
  • 冗余子集原则,有利于降低后续IO开销
  • 明细层事实表维度退化,减少后续使用join成本

3.3)周期快照事实表

  • 周期快照事实表中的每行汇总了发生在某一标准周期,如某一天,某周,某月的多个度量事件
  • 粒度是周期性的,不是个体的事务
  • 通常包含许多事实,因为任何与事实表粒度一致的度量事件都是被允许的

3.4)累计快照事实表

  • 多个业务过程联合分析而构建的事实表,如采购单的流转环节
  • 用于分析事件时间和时间之间的间隔周期
  • 少量的且当前事务型不支持的,如关闭、发货等相关的统计

4)DWS公共汇总层设计规范

数据仓库的性能是数据仓库建设是否成本的重要标准之一。聚集主要是通过汇总明细粒度数据来获得改进查询性能的效果。通过访问聚集效果,可以减少数据库在响应查询时必须执行的工作量,能够快速响应用户的查询,同时有利于减少不同访问明细数据带来的结果不一致的问题。

4.1)聚集的基本原则

  • 一致性:聚集表必须提供与查询明细粒度数据一致的查询效果
  • 避免单一表设计:不要在同一个表中存储不同层次的聚集数据
  • 聚集粒度可不同:聚合并不需要保持与原始明细粒度数据一样的粒度,聚集只关心所需要查询的维度。

4.2)聚集的基本步骤

  • 第一步:确定聚集维度

    在原始明细模型中会存在多个描述事实的维度,如日期、商品类别、卖家等,这时候需要确定根据什么维度聚集,如果只关心商品的交易额情况,那么就可以根据商品维度聚集数据

  • 第二步:确定一致性上钻

    这时候要关心是按月汇总还是按天汇总,是按照商品汇总还是按照类目汇总,如果按照类目汇总,还需要关心是按照大类汇总还是小类汇总。当然,我们要做的还是了解用户需要什么,然后按照他们的需求进行聚集

  • 第三步:确定聚集事实

    在原始明细模型中可能会有多个事实的度量,比如在交易中有交易额、交易数量等,这时候要明确是按照交易额汇总还是按照成交数量汇总

4.3)公共汇总层设计原则

除了聚集基本的原则外,公共汇总层还必须遵循以下原则:

  • 数据公用性:汇总的聚集会有第三者使用吗?基于某个维度的聚集是不是经常用于数据分析中?如果答案是肯定的,那么就有必要把明细经过汇总沉淀到聚集表中
  • 不跨数据域:数据域是在较高层次上对数据进行分类聚集的抽象
  • 区分统计周期:在表的命名上要能说明数据的统计周期,如_id表示最近一天,_td表示介质当天,_nd表示最近N天

3.数仓命名规范

1)词根设计规范

词根属于数仓建设中的规范,属于元数据管理范畴,现在把这个划到数据治理的一部分。完整的数仓建设是包含数据治理的,只是现在谈到数仓偏向于数据建模,而谈到数据治理,更多的是关于数据规范、数据管理。

表命名,其实在很大程度上是对元数据描述的一种体现,表命名规范越完善,我们能从表名获取到的信息就越多。比如:一部分业务是关于货架的,英文名是rack,rack就是一个词根,那么我们所有表、字段等用到的地方都叫rack,不要叫成别的什么。这就是词根的作用,用来统一命名,表达同一个含义。指标体系中有很多“率”的指标,都可以拆解为***+率,率也就是rate,那么所有关于指标的地方都使用***+rate

词根可以用来统一表名、字段名、主题域名等

  • 数仓层次

    ODS层:ods
    DWD层:dwd
    DWS层:dws
    公共维度:dim
    DM层:dm
    
  • 周期/数据范围

    日快照:d
    增量:i
    全量:f
    周:w
    拉链表:l
    非分区全量表:a
    

2)表命名规范

2.1)常规表

常规表是偶们需要固化的表,是正式使用的表,是目前一段时间内需要维护的完善的表

规范:分层前缀[dwd_dws_ads]_部门_业务域_主题域_自定义_更新周期|数据范围

业务域、主题域都可以用词根的方式枚举清楚,不断完善

更新周期主要的是时间粒度,日、周、月、年等

2.2)中间表

中间表一般出现在job中,是job中临时存储的中间数据的表,中间表的作用域只限于当前Job执行过程中,Job一旦执行完成,该中间表的使命就完成了,是可以删除的, 不过根据公司具体情况可以保留几天。

规范:mid_table_name_[0-9|dim]

table_name是任务中目标表的名字,通常来说一个任务只有一个目标表。这里加上表名,是为了防止自由发挥的时候表明冲突,而末尾可以自定义。

通常遇到需要补全维度的表,可以使用dim结尾

如果要保留历史的中间表,可以加上日期或者时间戳

2.3)临时表

临时表是临时测试的表,是临时使用一次的表,就是暂时保持下数据看看,后续一般不再使用的表,是可以随时删除的表。

规范:tmp_xxx

只要加上tmp开头即可,其他名字随意,注意tmp开头的表不要用来实际使用,只是为了测试验证

2.4)维度表

维度表是基于底层数据,抽象出来的描述类的表。维度表可以自动从底层抽象出来,也可以手工来维护

规范:dim_xxx

维度表,统一以dim,后面加工,对该指标的描述

2.5)手工表

手工表是手工维护的表,手工初始化之后,一般不会自动改变,后面变更,也是手工来维护。

一般来说,手工的数据粒度是偏细的,所以暂时统一放在dwd层,后面如果有目标值或者其他类型的手工数据,再根据实际情况分层。

规范:dwd_业务域_manual_xxx

3)指标命名规范

3.1)公共规则文章来源地址https://www.toymoban.com/news/detail-598247.html

  • 所有单词小写(正确:ods 错误:Ods)
  • 单词之间下划线分割(正确:order_type 错误:orderType)
  • 可读性由于长度(词根,避免出现同一个指标,命名一致性)
  • 禁止使用sql关键字,如字段名与关键字冲突时 + col
  • 数量字段后缀_cnt等标识
  • 金额字段后缀_price等标识
  • 天分区使用字段dt,格式统一(yyyymmdd 或 yyyy-mm-dd)
  • 小时分区使用字段hh,范围(00-23)
  • 分钟分区使用字段mi,范围(00-59)
  • 布尔类型标识:is_{业务},不允许出现控制

到了这里,关于《数据仓库》一文读懂数据仓库建设的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 离线数仓同步数据1

    com.atguigu.gmall.flume.interceptor.TimestampInterceptor$Builder

    2024年02月10日
    浏览(37)
  • 看这篇就明白大数据实时数仓、离线数仓、数据湖之间的关系

      20世纪70年代,MIT(麻省理工)的研究员致力于研究一种优化的技术架构,该架构试图将业务处理系统和分析系统分开,即将业务处理和分析处理分为不同层次,针对各自的特点采取不同的架构设计原则,MIT的研究员认为这两种信息处理的方式具有显著差别,以至于必须采取完

    2024年02月08日
    浏览(47)
  • 离线数仓(一)【数仓概念、需求架构】

            今天开始学习数仓的内容,之前花费一年半的时间已经学完了 Hadoop、Hive、Zookeeper、Spark、HBase、Flume、Sqoop、Kafka、Flink 等基础组件。把学过的内容用到实践这是最重要的,相信会有很大的收获。         数据仓库( Data Warehouse ),是 为企业制定决策,提供数

    2024年02月20日
    浏览(41)
  • 离线数仓分层

    1、清晰数据结构 :数仓每一层都有对应的作用,方便在使用时更好定位与了解 2、数据血缘追踪 :清晰知道表/任务上下游,方便排查问题,知道下游哪个模块在使用,提升开发效率及后期管理维护 3、减少重复开发 :完善数仓好中间层,减少后期不必要的开发,从而减少资

    2024年02月06日
    浏览(39)
  • 阿里云生态离线数仓

            功能齐全:10多年大数据建设沉淀完整的平台,覆盖数据开发治理的全生命周期         简单易用:全图形化界面,SQL为主的数据开发方式         安全稳定:双11日千万级任务稳定调度,金融级数据安全保障         开放兼容: 支持多种大数据引擎绑定,开放

    2024年02月05日
    浏览(33)
  • 一百八十六、大数据离线数仓完整流程——步骤五、在Hive的DWS层建动态分区表并动态加载数据

    经过6个月的奋斗,项目的离线数仓部分终于可以上线了,因此整理一下离线数仓的整个流程,既是大家提供一个案例经验,也是对自己近半年的工作进行一个总结。 1、Hive的DWS层建库建表语句 --如果不存在则创建hurys_dc_dws数据库 create database if not exists hurys_dc_dws; --使用hurys_

    2024年02月07日
    浏览(47)
  • 【从0开始离线数仓项目】——新能源汽车数仓项目介绍

    目录 1、数据仓库概念 2、项目需求及架构设计 3、集群资源规划设计  4、车辆日志字段说明 数据仓库(Data Warehouse)是为企业提供数据支持,用以协助企业制定决策、改进业务流程和提高产品质量等方面的工具。它可以接收多种类型的输入数据,如业务数据、日志数据和爬虫

    2024年02月13日
    浏览(40)
  • 数据仓库建设-数仓分层

    数据仓库能够帮助企业做出更好的决策,提高业务效率和效益;在数据仓库建设时,绕不开的话题就是数仓分层。 1. 降低数据开发成本 通用的业务逻辑加工好,后续的开发任务可以基于模型快速使用,数据需求的响应速度也会更快。 2. 降低任务运维成本 业务发展过程中,数

    2024年02月16日
    浏览(45)
  • 一百八十二、大数据离线数仓完整流程——步骤一、用Kettle从Kafka、MySQL等数据源采集数据然后写入HDFS

    经过6个月的奋斗,项目的离线数仓部分终于可以上线了,因此整理一下离线数仓的整个流程,既是大家提供一个案例经验,也是对自己近半年的工作进行一个总结。 项目行业属于交通行业,因此数据具有很多交通行业的特征,比如转向比数据就是统计车辆左转、右转、直行

    2024年02月07日
    浏览(52)
  • 离线数仓中,为什么用两个flume,一个kafka

    实时数仓中,为什么没有零点漂移问题? 因为flink直接取的事件时间 用kafka是为了速度快,并且数据不丢,那为什么既用了kafkachannel,也用了kafka,而不只用kafkachannel呢? 因为需要削峰填谷 离线数仓中,为什么用两个flume,一个kafka,直接用taildirsource,kafkachannel,hdfssink不行吗?

    2024年02月14日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包