企业级大数据项目之数据仓库.docx
《企业级大数据项目之数据仓库.docx》由会员分享,可在线阅读,更多相关《企业级大数据项目之数据仓库.docx(60页珍藏版)》请在冰豆网上搜索。
企业级大数据项目之数据仓库
企业级大数据项目之数据仓库
第1章数据仓库简介
1.1什么是数据仓库
1.1.1数据仓库的概念
官方定义:
数据仓库是一个面向主题的、集成的、随时间变化的、但信息本身相对稳定的数据集合,用于对管理决策过程的支持。
这个定义的确官方,但是却指出了数据仓库的四个特点。
特点:
面向主题:
数据仓库都是基于某个明确主题,仅需要与该主题相关的数据,其他的无关细节数据将被排除掉
集成的:
从不同的数据源采集数据到同一个数据源,此过程会有一些ETL操作
随时间变化:
关键数据隐式或显式的基于时间变化
信息本身相对稳定:
数据装入以后一般只进行查询操作,没有传统数据库的增删改操作
大白话:
数据仓库就是整合多个数据源的历史数据进行细粒度的、多维的分析,帮助高层管理者或者业务分析人员做出商业战略决策或商业报表。
1.1.2数据仓库的用途
●整合公司所有业务数据,建立统一的数据中心
●产生业务报表,用于作出决策
●为网站运营提供运营上的数据支持
●可以作为各个业务的数据源,形成业务数据互相反馈的良性循环
●分析用户行为数据,通过数据挖掘来降低投入成本,提高投入效果
●开发数据产品,直接或间接地为公司盈利
●…
1.1.3数据库和数据仓库的区别
差异项
数据库
数据仓库
特征
操作处理
信息处理
面向
事务
分析
用户
DBA、开发
经理、主管、分析人员
功能
日常操作
长期信息需求、决策支持
DB设计
基于ER模型,面向应用
星形/雪花模型,面向主题
数据
当前的、最新的
历史的、跨时间维护
汇总
原始的、高度详细
汇总的、统一的
视图
详细、一般关系
汇总的、多维的
工作单元
短的、简单事务
复杂查询
访问
读/写
大多为读
关注
数据进入
信息输出
操作
主键索引操作
大量的磁盘扫描
用户数
数百到数亿
数百
DB规模
GB到TB
>=TB
优先
高性能、高可用性
高灵活性
度量
事务吞吐量
查询吞吐量、响应时间
1.2数据仓库的架构
1.2.1理想架构
一个相对比较成熟的数据仓库架构模型如下:
图1-1数据仓库架构图
数据采集
数据采集层的任务就是把数据从各种数据源中采集和存储到数据存储上,期间有可能会做一些ETL操作,例如采用Flume收集日志,采用Sqoop将RDBMS以及NoSQL中的数据同步到HDFS上
数据源种类可以有多种:
●日志:
所占份额最大,存储在备份服务器上;
●业务数据库:
如Mysql、Oracle;
●来自HTTP/FTP的数据:
合作伙伴提供的接口;
●其他数据源:
如Excel等需要手工录入的数据;
数据存储与分析
●HDFS是大数据环境下数据仓库/数据平台最完美的数据存储解决方案;
●离线数据分析与计算,也就是对实时性要求不高的部分,Hive是不错的选择;
●使用Hadoop框架自然而然也提供了MapReduce接口,如果真的很乐意开发Java,或者对SQL不熟,那么也可以使用MapReduce来做分析与计算;
●Spark性能比MapReduce好很多,同时使用SparkSQL操作Hive;
●可以加入Kafka防止数据丢失;
●实时计算使用SparkStreaming消费Kafka中收集的日志数据,实时计算结果大多保存在Redis中;
数据共享
前面使用Hive、MR、Spark、SparkSQL分析和计算的结果,还是在HDFS上,但大多业务和应用不可能直接从HDFS上获取数据,那么就需要一个数据共享的地方,使得各业务和产品能方便的获取数据。
这里的数据共享,其实指的是前面数据分析与计算后的结果存放的地方,其实就是关系型数据库和NOSQL数据库。
数据应用
报表:
报表所使用的数据,一般也是已经统计汇总好的,存放于数据共享层。
接口:
接口的数据都是直接查询数据共享层即可得到。
即席查询:
即席查询通常是现有的报表和数据共享层的数据并不能满足需求,需要从数据存储层直接查询。
一般都是通过直接操作SQL得到。
机器学习:
使用了SparkMLlib提供的机器学习算法
多维分析OLAP:
使用Kylin作为OLAP引擎;
数据可视化:
提供可视化前端页面,方便运营等非开发人员直接查询;
1.3数据仓库多维数据模型的设计
1.3.1基本概念
主题(Subject)
主题就是指我们所要分析的具体方面。
例如:
某年某月某地区某机型某款App的安装情况。
主题有两个元素:
一是各个分析角度(维度),如时间位置;二是要分析的具体量度,该量度一般通过数值体现,如App安装量。
维(Dimension)
维是用于从不同角度描述事物特征的,一般维都会有多层(Level:
级别),每个Level都会包含一些共有的或特有的属性(Attribute),可以用下图来展示下维的结构和组成:
图1-2维的结构及组成
以时间维为例,时间维一般会包含年、季、月、日这几个Level,每个Level一般都会有ID、NAME、DESCRIPTION这几个公共属性,这几个公共属性不仅适用于时间维,也同样表现在其它各种不同类型的维。
分层(Hierarchy)
OLAP需要基于有层级的自上而下的钻取,或者自下而上地聚合。
所以我们一般会在维的基础上再次进行分层,维、分层、层级的关系如下图:
图1-3分层关系
每一级之间可能是附属关系(如市属于省、省属于国家),也可能是顺序关系(如天周年),如下图所示:
图1-4附属关系
图1-5顺序关系
量度
量度就是我们要分析的具体的技术指标,诸如年销售额之类。
它们一般为数值型数据。
我们或者将该数据汇总,或者将该数据取次数、独立次数或取最大最小值等,这样的数据称为量度。
粒度
数据的细分层度,例如按天分按小时分。
事实表和维表
事实表是用来记录分析的内容的全量信息的,包含了每个事件的具体要素,以及具体发生的事情。
事实表中存储数字型ID以及度量信息。
维表则是对事实表中事件的要素的描述信息,就是你观察该事务的角度,是从哪个角度去观察这个内容的。
事实表和维表通过ID相关联,如图所示:
图1-6事实表与维度表
星形/雪花形/事实星座
这三者就是数据仓库多维数据模型建模的模式
上图所示就是一个标准的星形模型。
雪花形就是在维度下面又细分出维度,这样切分是为了使表结构更加规范化。
雪花模式可以减少冗余,但是减少的那点空间和事实表的容量相比实在是微不足道,而且多个表联结操作会降低性能,所以一般不用雪花模式设计数据仓库。
事实星座模式就是星形模式的集合,包含星形模式,也就包含多个事实表。
企业级数据仓库/数据集市
企业级数据仓库:
突出大而全,不论是细致数据和聚合数据它全都有,设计时使用事实星座模式
数据集市:
可以看做是企业级数据仓库的一个子集,它是针对某一方面的数据设计的数据仓库,例如为公司的支付业务设计一个单独的数据集市。
由于数据集市没有进行企业级的设计和规划,所以长期来看,它本身的集成将会极其复杂。
其数据来源有两种,一种是直接从原生数据源得到,另一种是从企业数据仓库得到。
设计时使用星形模型
1.3.2数据仓库设计步骤
a、确定主题
主题与业务密切相关,所以设计数仓之前应当充分了解业务有哪些方面的需求,据此确定主题
b、确定量度
在确定了主题以后,我们将考虑要分析的技术指标,诸如年销售额之类。
量度是要统计的指标,必须事先选
择恰当,基于不同的量度将直接产生不同的决策结果。
c、确定数据粒度
考虑到量度的聚合程度不同,我们将采用“最小粒度原则”,即将量度的粒度设置到最小。
例如如果知道某些数据细分到天就好了,那么设置其粒度到天;但是如果不确定的话,就将粒度设置为最小,即毫秒级别的。
d、确定维度
设计各个维度的主键、层次、层级,尽量减少冗余。
e、创建事实表
事实表中将存在维度代理键和各量度,而不应该存在描述性信息,即符合“瘦高原则”,即要求事实表数据条数尽量多(粒度最小),而描述性信息尽量少。
第2章项目框架
2.1项目概述
当前,所有应用到大数据的公司都需要建设企业数据仓库,以服务于数据分析和为企业决策、产品优化、产品运营等提供稳定可靠的数据支持,因此,数据仓库的建设在公司数据的E(抽取)、T(转化)、L(加载)流程中起到至关重要的地位。
对于就业而言,数据仓库方向也是大数据相关的一个很重要的细分领域,这不仅体现在数据仓库方向能够承载较大的就业,也体现在数据仓库在是数据分析、数据挖掘、以及机器学习的数据来源和知识基础,所以,了解数据仓库理论模型和掌握数据仓库实操对于职业发展也是非常重要的。
2.2项目框架
图2-1项目框架
根据图2-1的项目框架可知,本项目由数据采集系统和基于Hive数据处理系统两个部分组成。
数据采集系统采用了双层Flume拓扑结构,第一层实现数据的采集,第二层实现数据利用Flume的自定义拦截器达到分类处理,使得不同的类别的日志能够自动存储到Kafka集群中不同的Topic中;手机APP客户端的日志数据被日志采集系统采集完成后,被输送到HDFS分布式文件系统后以便利用Hive来进行数据处理系统中进行处理。
首先,APP客户端的日志数据经过埋点上报,服务器端通过Nginx实现负载均衡,Nginx将日志数据负载均衡到多个采集服务器上,采集服务器通过log4j将日志数据写入日志文件中,通过日志数据的落盘实现了业务系统与数据采集系统的解耦。
随后,双层Flume架构中的第一层数据采集Flume将对应的采集服务器生成的日志文件采集到其拓扑结构中,随后多个第一层数据采集Flume的数据汇总到第二层的数据聚合Flume上,完成数据的聚合和集中处理。
然后,第二层的数据聚合Flume根据由自定义的拦截器根据日志数据的类型,将日志数据发送到不同的Kafka主题中,在Kafka中完成数据的分布式存储。
最后,利用FlumeAgent从Kafka中消费消息,完成数据的离线分析处理。
2.3日志分析
2.3.1日志上报流程
本项目数据日志采用埋点产生,日志上报主要分为点击上报以及曝光上报。
点击上报是实时上报,曝光上报是跟最近的一次点击上报一起上报。
2.3.2日志数据样例
字段分别为App名称,操作系统(android和ios),IP地址,用户ID,日志类型(click、view、page),手机品牌,网络,用户行为操作时间戳,页面ID,来源页面类型
2.4产品选型
2.4.1Kafka选型
图1-4Kafka选型依据
由于需要使用SparkStreaming对接Kafka,因此我们需要参照Spark官网的说明去选择Kafka版本,由于SparkStreaming与Kafka0.10版本尚处于实验阶段,不能保证稳定性,因此,本项目使用0.8版本的Kafka。
2.4.1Flume选型
图1-5Flume选型依据
由于1.7版本的Flume只支持0.8以上版本(不包括0.8版本)的KafkaSink,因此我们使用1.6版本的Flume。
2.4.1产品选型列表
表1-7产品选型列表
名称
版本
Nginx
nginx-1.12.2
Tomcat
apache-tomcat-7.0.72
Hadoop
hadoop-2.7.2
Spark
spark-2.1.1-bin-hadoop2.7
Flume
apache-flume-1.6.0-bin
Kafka
kafka_2.11-0.8.2.1
Hive
apache-hive-1.2.2-bin
Hbase
hbase-1.2.6
第三章预备知识
3.1Flume
3.1.1Flume组件介绍
表1-8Flume组件介绍
名称
解析
Event
一个数据单元,带有一个可选的消息头,其实就是一条消息,一个日志;(Kafka的消息没有消息头,因此,Flume的消息进入Kafka后,消息头就丢失了)
Flow
数据流,Event从源点到达目的点的迁移的抽象
Client
操作位于源点处的Event,将其发送到FlumeAgent
Agent
一个独立的Flume进程,包含组件Source、Channel、Sink
Source
用来获取Event并写入Channel
Channel
中转Event的一个临时存储,保存有Source组件传递过来的Event,可以认为是一个队列
Sink
从Channel中读取并移除Event,将Event传递到FlowPipeline中的下一个Agent或者其他存储系统
3.1.2Flume组件选择
第一层agent:
lSource:
TailDirSource
lChannel:
FileChannel
lSink:
AvroSink
注意,TailDirSource是Flume1.7提供的Source组件,在1.6中并没有,因此,需要从1.7中移植到1.6中。
第二层agent:
lSource:
AvroSource
lChannel:
FileChannel
lSink:
KafkaSink
3.1.3Flume采集系统组件解析
1.Source
1)AvroSource
侦听Avro端口并从外部Avro客户端流接收事件。
当与另一个(上一跳)Flume代理的内置AvroSink配对时,它可以创建分层收集拓扑。
2)TaildirSource
在Flume1.7之前如果想要监控一个文件新增的内容,我们一般采用的source为exectail,但是这会有一个弊端,就是当你的服务器宕机重启后,此时数据读取还是从头开始,这显然不是我们想看到的!
在Flume1.7没有出来之前我们一般的解决思路为:
当读取一条记录后,就把当前的记录的行号记录到一个文件中,宕机重启时,我们可以先从文件中获取到最后一次读取文件的行数,然后继续监控读取下去。
保证数据不丢失、不重复。
在Flume1.7时新增了一个source的类型为taildir,它可以监控一个目录下的多个文件,并且实现了实时读取记录保存的断点续传功能。
但是Flume1.7中如果文件重命名,那么会被当成新文件而被重新采集。
2.Channel
1)MemoryChannel
MemoryChannel把Event保存在内存队列中,该队列能保存的Event数量有最大值上限。
由于Event数据都保存在内存中,MemoryChannel有最好的性能,不过也有数据可能会丢失的风险,如果Flume崩溃或者重启,那么保存在Channel中的Event都会丢失。
同时由于内存容量有限,当Event数量达到最大值或者内存达到容量上限,MemoryChannel会有数据丢失。
2)FileChannel
FileChannel把Event保存在本地硬盘中,比MemoryChannel提供更好的可靠性和可恢复性,不过要操作本地文件,性能要差一些。
3)KafkaChannel
KafkaChannel把Event保存在Kafka集群中,能提供比FileChannel更好的性能和比MemoryChannel更高的可靠性。
3.Sink
1)AvroSink
AvroSink是Flume的分层收集机制的重要组成部分。
发送到此接收器的Flume事件变为Avro事件,并发送到配置指定的主机名/端口对。
事件将从配置的通道中按照批量配置的批量大小取出。
2)KafkaSink
KafkaSink将会使用FlumeEventheader中的topic和key属性来将event发送给Kafka。
如果FlumeEvent的header中有topic属性,那么此event将会发送到header的topic属性指定的topic中。
如果FlumeEvent的header中有key属性,此属性将会被用来对此event中的数据指定分区,具有相同key的event将会被划分到相同的分区中,如果key属性null,那么event将会被发送到随机的分区中。
可以通过自定义拦截器来设置某个event的header中的key或者topic属性。
3.1.4Flume拓扑结构
图2-1FlumeAgent连接
图2-2FlumeAgent聚合
图2-3Flume多路Flow
图2-4Flume负载均衡
3.1.5FlumeSource、Channel处理器、拦截器和Channel选择之间的交互
图2-5Flume负载均衡
1.接收事件;
2.处理事件;
3.将事件传递给拦截器链;
4.将每个事件传递给Channel选择器;
5.返回写入事件的Channel列表;
6.将所有事件写入每个必需的Channel,只有一个事务被打开;对于每个Channel,所有事件都写为事务的一部分;
7.利用可选Channel重复相同动作。
Flume本身不限制Agent中Source、Channel和Sink的数量。
因此FlumeSource可以接收事件,并可以通过配置将事件复制到多个目的地。
这使得Source通过Channel处理器、拦截器和Channel选择器,写入数据到Channel成为可能。
每个Source都有自己的Channel处理器。
每次Source将数据写入Channel,它是通过委派该任务到其Channel处理器来完成的。
然后,Channel处理器将这些事件传到一个或多个Source配置的拦截器中。
拦截器是一段代码,可以基于某些它完成的处理来读取时间和修改或删除时间。
基于某些标准,如正则表达式,拦截器可以用来删除事件,为事件添加新报头或移除现有的报头等。
每个Source可以配置成使用多个拦截器,按照配置中定义的顺序被调用,将拦截器的结果传递给链的下一个单元。
这就是所谓的责任链的设计模式。
一旦拦截器处理完事件,拦截器链返回的事件列表传递到Channel列表,即通过Channel选择器为每个事件选择的Channel。
Source可以通过处理器-拦截器-选择路由器写入多个Channel。
Channel选择器是决定每个事件必须写入到Source附带的哪个Channel的组件。
因此拦截器可以用来插入或删除事件中的数据,这样Channel选择器可以应用一些条件在这些事件上,来决定事件必须写入哪些Channel。
Channel选择器可以对事件应用任意过滤条件,来决定每个事件必须写入哪些Channel,以及哪些Channel是必需的或可选的。
写入到必需的Channel失败将会导致Channel处理器抛出ChannelException,表明Source必须重试该事件(实际上,所有的时间都在那个事务中),而未能写入可选Channel失败仅仅忽略它。
一旦写出事件,处理器将会对Source指示成功状态,可能发送确认(ACK)给发送该事件的系统,并继续接受更多的事件。
1.拦截器
拦截器(Interceptor)是简单插件式组件,设置在Source和Source写入数据的Channel之间。
Source接收到的事件在写入到对应的Channel之前,拦截器都可以转换或删除这些事件。
每个拦截器实例只处理同一个Source接收到的事件。
拦截器可以基于任意标准或转换事件,但是拦截必须返回尽可能多(或尽可能少)的事件,如同原始传递过来的事件。
多个拦截器组成一个有序的拦截器链。
在一个链条中,可以添加任意数量的拦截器去转换从单个Source中来的事件。
Source将同一个事务的所有事件传递给Channel处理器,进而传递给拦截器链条,然后事件被传递给链条中的第一个拦截器。
通过拦截器转换时间产生的一系列事件,传递到链条的下一个拦截器,以此类推。
链条最后一个拦截器返回的最终事件列表写入到Channel中。
因为拦截器必须在事件写入Channel之前完成转换操作,只有当拦截器已成功转换事件后,RPCSource(和任何其他可能产生超时的Source)才会响应发送事件的客户端或Sink。
因此,在拦截器中进行大量重量级的处理并不是和一个好主意。
如果拦截器中的处理时重量级的、耗时的,那么需要相应地调整超时时间属性。
Flume配置文件中,所有拦截器通用的唯一配置参数是type参数,改参数必须是拦截器的别名或者Builder类的完全限定类名(FQCN),该Builder类用于创建拦截器。
正如前面提到的,可以设置任意数量的拦截器连接到单个的Source。
拦截器是需要命名的组件,每个拦截器实例必须限定一个名字。
为了给Source添加拦截器,需要列出Source应该连接的拦截器名字,这些拦截器就是Source应该连接到Source配置中interceptors参数的值代表的拦截器。
原配置中以interceptors.开头的、后面跟着拦截器名称和参数的所有值都传递给拦截器。
2.Channel选择器
Channel选择器是决定Source接收的一个特定事件写入哪些Channel的组件。
它们告知Channel处理器,然后将事件写入到每个Channel。
由于Flume并不是两阶提交(不会等所有事件都写入成功后再一起提交,而是写一个提交一个),事件被写入到一个Channel,然后在事件被写入到下一个Channel之前提交。
如果写入一个Channel时出现故障,可能已经发生在其他Channel的相同事件的写入不能被回滚。
当这样的故障发生时,Channel处理器抛出ChannelException并且事务失败。
如果Source试图再次写入相同的事件(在大多数情况下,它会重试,只有类似Syslog、Exec等Source不能重试,因为没有办法再次生成相同的数据),重复的事件将写入到Channel,而先前的提交实际上是成功的,这是在Flume管道发生重复的一种情况。
Channel选择器配置是通过Channel处理器完成的,虽然配置看起来像Source子组件的配置。
传递到Channel选择器的所有参数作为Source的上下文中的参数使用selector后缀传递。
对于每个Source,选择器通过使用一个配置参数type指定。
Channel选择器可以指定一组Channel是必需的(required),另一组是可选的(optional)。
Flume内置两种Channel选择器:
replicating和mutiplexing。
如果Source的配置中没有指定选择器,那么会自动使用复制Channel选择器。
replicatingChannel选择器复制每个事件到Source的channels参数所指定的所有Channel中。
multiplexingChannel选择器是一种专门用于动态路由事件的Channel选择器,通过选择事件应该写入的Channel,基于一个特定的事件头的值进行路由。
3.1.6FlumeSink、Sink运行器、Sink组和Sink处理器
图2-6FlumeSink、Sink运行器、Sink组合Sink处理器
Sink运行器(SinkRunner)运行一个Sink组(SinkGroup),Sink组可以含有一个或多个Sink。
如果组中只存在一个Sink,那么没有组将会更有效率。
Sink运行器仅仅是一个询问Sink组(或Sink)来处理下一批事件的线程。
每个Sink组有一个Sink处理器(