1. 前言
数据仓库代表的是一种对数据的管理和使用的方式,它是一整套包括了etl、调度、建模在内的完整的理论体系。现在所谓的大数据更多的是一种数据量级的增大和工具的上的更新。 两者并无冲突,相反,而是一种更好的结合。单纯使用 Hadoop、Spark、Flume 处理处理数据,其实只是学会几种新的工具,这是搞工具的,只是在数据仓库中etl中的一部分。技术的更新往往能领到一个时代的变革,比如Hadoop的诞生,光是深入研究一个大数据组件就要花很大的时间和精力。对于数据的从业者来讲,要始终重视紧跟技术的变革,但是切记数据为王,在追求技术的极致的时候,不要忘了我们是搞数据的。
本文对数据分层的讨论适合下面一些场景
- 数据建设刚起步,大部分的数据经过粗暴的数据接入后就直接对接业务。
- 数据建设发展到一定阶段,发现数据的使用杂乱无章,各种业务都是从原始数据直接计算而得。
- 各种重复计算,严重浪费了计算资源,需要优化性能。
2. 为什么要分层
我们对数据进行分层的主要原因就是希望在管理数据的时候,能对数据有一个更加清晰的掌控。
详细来讲,主要有下面几个原因:
- 清洗数据结构: 每一个数据分层都有它的作用域,这样我们在使用表的时候能更方便地定位和理解。
- 数据血缘跟踪:简单来讲有一张源表出问题,我们希望能够快速准确地定位到问题,并清除它的危害范围。
- 减少重复开发:规范数据分层,开发一些通用的中间层数据,能够减少极大的重复计算。
- 把复杂问题简单化:将一个复杂的任务分解成多个步骤来完成,每层只处理单一的步骤,比较简单和容易理解。而且便于维护数据的准确性。
- 屏蔽业务的影响:不必改一次业务就需要重新接入数据。
3.数据仓库分层介绍
我们从理论上来做一个抽象,可以把数据仓库分为下面三个层,即:数据运营层、数据仓库层和数据产品层。
3.1 ODS
ODS 是 Operational Data Store 的简写,即操作数据存储层,或叫数据运营层。
ODS层是最接近数据源中数据的一层,数据源中的数据经过抽取、清洗、传输, 也就是传说中的ETL 之后, 装入本层。
ODS层的数据,总体上大多是按照源头业务系统的分类方式而分类的。
例如这一层可能包含的数据表为:
- 人口表(包含每个人的身份证号、姓名、住址等)
- 机场登机记录(包含乘机人身份证号、航班号、乘机日期、起飞城市等)
- 银联的刷卡信息表(包含银行卡号、刷卡地点、刷卡时间、刷卡金额等)
- 银行账户表(包含银行卡号、持卡人身份证号等) 等
这里我们可以看到,这一层的数据还具有鲜明的业务数据库的特征,甚至还具有一定的关系数据库中的数据范式的组织形式。
层的数据却不等同于原始数据。在源数据转入这一层时,要进行数据清洗操作,如:
- 去燥:从原始数据中去掉明显偏离正常水平的数据,如银行刷卡异常信息
- 去重:数据去重,例如银行账户信息、公安局人口信息中均含有认得姓名,但是只保留一份即可)、
- 提脏:清理脏数据,例如有人的银行卡被盗刷,在十分钟内同时有两笔分别在中国和日本刷卡信息,这便是脏数据
- 业务提取、单位统一:、砍字段,例如用于支撑前端系统工作,但是在数据挖掘中不需要的字段等操作
3.2 DW
- 数据仓库层(DW),是数据仓库的主体。
- DW层从ODS(Operation Data Store)层中获得的数据按照主题建立各种数据模型。
- 例如以研究人的旅游消费为主题的数据集中,便可以结合航空公司的登机出行信息,以及银联系统的刷卡记录,进行结合分析,产生数据集。
- 在这里我们需要了解四个概念:维(dimension)、事实(fact)、指标(index) 和粒度(Granularity)
3.3 APP 数据产品层
- APP层 即 数据产品层,为数据产品提供使用的结果数据。
- APP层主要是提供给数据产品和数据分析使用的数据,
- APP层的数据一般会存放在es、mysql等系统中供线上系统使用,也可能会存在Hive 或者Druid中供数据分析和数据挖掘使用。
- 比如我们经常说的报表数据,或者那种大宽表,一般就属于这一层。
3. 数据实践
这三层技术划分,相对来说比较粗粒度,后面我们会专门细分一下。在此之前,先聊一下每一层的数据一般都是怎么流向的。这仅仅简单介绍几个常用的工具,侧重开源界的主流。
3.1 数据来源层–>ODS 层
这里其实就是我们现在大数据技术发挥作用的主要战场。我们的数据主要会有两个大的来源:
业务库,这里经常会使用sqoop 来抽取比如我们每天定时抽取一次。在实施方面,可以考虑canal 监听mysql的binlog ,实时介入即可。
埋点日志,线上系统会打入各种日志,这些日志一般以文件的形式保存,我们可以选择用flume定时抽取,也可以用spark streaming 或者storm 来实时接入,这时kafka也会是一个关键的角色。
其他数据源会比较多样性,这和具体的业务相关,不再赘述。
注意:在这层,理应不是简单的接收数据,而要考虑一定的数据清洗,比如异常字段的处理、字段命名规范化、时间字段的统一等,一般这些很容易被忽略,但确实至关重要的。特别是后期我们做各种特征自动生成的时候,会十分有用。
3.2 ODS、DW–>APP层
这里面也主要分为两种类型:
每日定时任务:比如我们典型的日计算任务,每天凌晨算前一天的数据,早上起来看报表。这种任务经常使用Hive、Spark或者MR程序来计算,最终写入Hive、Hbase、Mysql、Es 或者Redis中
实时数据:这部分主要是各种实时的系统使用,比如我们的实时推荐、实时用户画像、一般我们会使用Spark streaming、Storm 或者flink 来计算,最后虎落入Es、Hbase或者Redis中。
- 举个例子
早起参与设计的数据分层例子。分析一下当初的想法,以及各种设计缺陷。上原图(此处@Ruby大神。现实是我只是个打酱油的。盗图、盗思想)
当初设计共分6层,其中去掉元数据后还有5层。下面分析一下当初的一个设计思路。
3.2.1 缓冲层
缓冲层(buffer)又称为接口层(stage),用于存储每天的增量数据和变更数据,比如Canal接收的业务变更日志。
数据生成方式:直接从kafka接受数据源,需要业务每天生成update、delete、insert数据,只生成insert数据的业务表,数据直接插入明细层。
讨论方案:只把canal日志直接写入缓冲层,如果其他有拉链数据的业务,也加入缓冲层。
日志存储方式:使用impala外表,parquet文件格式,方便需要MR处理额数据读取。
日志删除方式:长久存储,可只存储最近祭坛的数据。讨论方案:直接长久存储
表schema: 一般按天创建分区
库与表命名:库名:buffer,表名:初步考虑格式为buffer_日期_业务表名
3.2.2 明细层
明细层(ODS Operational Data Store, DWD:data warehouse detail)是数据仓库的细节数据层,是对stage 层数据进行沉淀,减少了抽取的复杂性,同时ODS/DWD的信息模型组织主要遵循企业业务事务处理的形式,将各个专业数据进行加一种,明细层跟stage层的粒度一致,术语分析的公共资源
日志生成方式:部分数据支架来自kafka,部分数据为接口层数据与历史数据合成。canal日志合成数据的方式有待研究。
讨论方案:canal 数据的合成方式为:每天把明细层的前天全量数据和昨天数据合成一个新的数据表,覆盖旧表。同时使用历史镜像, 按周/按月/按年存储一个历史镜像到新表。
日志存储方式:直接使用impala 外表,parquet文件格式,canal合成数据为二次生成数据,建议使用内表,下面几层都是从impala生成的数据,建议都采用内表+静态/动态分区。
日志删除方式:长久存储。
表schema:一般按天创建分区,没有时间概念的按具体业务选择分区字段
库与表命名:库名:ods, 表名:ods_日期_业务表名
旧数据更新方式:直接覆盖
3.2.3 轻度汇总层
概念:轻度汇总层(MID 或DWB ,data warehouse basis)是数据仓库中DWD层和DM层之间的一个过渡层,是对DWD层生产数据进行轻度综合和汇总统计(可以把复杂的清洗,处理包含在内,如根据PV日志生成的会话数据)。轻度综合层与DWD的主要区别在于二者的应用领域不同,DWD的数据源于生产型系统,并未满足一些不可预见的需求而进行产店,轻度综合层则面向分析型应用进行细粒度的统计和沉淀
数据生成方式:由明细层按照一定的业务需求生成轻度汇总表。明细层需要复杂清洗的数据和需要MR处理的数据也经过处理后接入到轻度汇总层。
日志存储方式:内表,parquet文件格式。
日志删除方式:长久存储
表schema:一般按天创建分区,没有时间概念的额按具体业务选择分区字段。
库与表名:库名:dwd, 表名:初步考虑格式为:dwd_日期_业务表名
就数据更新方式:直接覆盖
3.2.4 主题层
主题层(DM,data market或DWS data warehouse service)又称数据集市或宽表。按照业务划分,如流量,订单,用户等,生成字段比较多的宽表,用于提供后续的业务查询,OLAP分析,数据分发等。
数据生成方式:由轻度汇总层和明细层数据计算生成。
日志存储方式:使用impala内表,parquet文件格式存储。
日志删除方式:长久存储
表schema:一般按天创建分区,没有时间概念的按具体业务选择分区字段。
库名与表名:库名:dm,表名:初步考虑格式为dm_日期_业务表名。
旧数据更新方式:直接覆盖。
3.2.5 应用层
应用层(APP)是根据业务需要,由前面三层数据统计而出的结果。可以直接提供查询展示,或导入mysql中使用。
数据生成方式:由明细层、轻度汇总层、数据集市层生成,一般要求数据主要来源于集市层。
日志存储方式:使用impala内表,parquet文件格式存储。
日志删除方式:长久存储
表schema:一般按天创建分区,没有时间概念的按具体业务选择分区字段。
库名与表名:库名:暂定apl,另外根据业务不同,不限定一定要一个库。
旧数据更新方式:直接覆盖。
4. 更优雅的设计数据分层
前面提到的一种设计其实相对来讲已经很详细了,但是可能会层次有一点多,而且在区分一张表到底该存放在什么位置的时候可能还有一点点疑惑。我们在这里再设计一套数据仓库的分层,同时在前面的基础上加上维度表和一些临时表的考虑,来让我们的方案更加优雅一些。
下面做了一些小的改动,我们去掉了上一节的Buff层,把数据集市层和轻度汇总层放在同一个层级上,同时独立出来了维度表和临时表。
这里解释一下DWS、DWD、DIM和TMP的作用
DWS:轻度汇总层,从ODS层中对用户的行为做一个初步的汇总,抽象出来一些通用的维度:时间、ip、id,并根据这些维度做一些统计值,比如用户每个时间段在不同登陆ip购买的商品数等。这里做一层轻度的汇总会让计算更加高效,在此基础上如果计算仅7天、30天、90天的行为的话会很快。我们希望80%的业务都能通过我们的DWS层计算而不是ODS。
DWD:这一层主要解决一些数据质量问题和数据的完整度问题。比如用户的资料信息来自于很多不同的表,而且京城出现延迟丢数据等问题,为了方便各个使用方更好地使用数据,我们可以在这一层做一个屏蔽。
DIM:这一层比较单纯,举个例子就明白,比如国家代码和国家名、地理位置、中文名、国旗图片等信息就存在DIM层中。
TMP:每一层的计算都会有很多临时表,专设一个DWTMP 层来存储我们数据仓库的临时表。
5.问答
问:dws 和 dwd 是并行而不是先后顺序?
答:并行的dw层
问:那其实对于同一个数据,这两个过程是串行的?
答:dws 会做汇总,dwd和ods 的粒度相同,这两层没有依赖关系
问:对呀,那这样dws里面的数据汇总没有经过数据质量和完整度的处理,或者单独做了这种质量相关的处理,为什么不在dwd智商再做汇总呢?我的疑问其实就是,dws的轻度汇总数据结果,有没有做数据质量的处理?
答:ods之间到dw就好,没必要经过dwd,我举个例子,你的浏览商品行为,我做一层轻度汇总,就直接放在dws了。但是你的资料表,要从好多表凑成一份,我们从四五分个人资料表中凑出来了一份完整地资料表放在了dwd中,然后在app层,我们要出一个画像表,包含用户资料和用户最近一年的行为,我们就直接从dwd中拿资料,然后再idws的基础上左一层统计, 就成了一个app表
问:嗯,那最后一个疑问,在现实生产中,可不可能存在计算dws时,会用到dwd表的情况?
答:不 这样一来就混乱了,dws不会一来dwd,dws只接轻度汇总,业务用的话都取app层。
问:dws针对的是行为,可以在某些维度上上卷的行为~
答:你这样理解吧,dws存事实表,dwd维度表
6.总结
数据分层是数据仓库非常重要的一个环节,他决定的不仅仅是一个层次的问题。还直接影响到后续的血缘分析、特征自动生成、元数据管理等一系列的建设。因此适于尽早考虑。
另外每一层的名字不必太过在意。自己按照喜好就好。