复习:
上节课从维度建模开始说的,维度建模是源自于数据集市,数据集市的概念是由拉尔夫金博尔提出来的,维度建模主要应用的领域是OLAP的领域,就是数据分析的场景,维度建模里面只有事实表和维度表,事实表就是现实世界中的操作型事件就放在事实表里面,事实表是由维度和度量来组成的,维度就是看数据的角度,他和主题的区别就主题是一个更大的角度,维度就是主题底下的某一些小的角度去观察度量,事实表中的每一个维度,都是会有一个维度表与它一一对应,就像主外键关联,可以在事实表里关联到更多的维度属性来对度量进行统计,那维度表更像是主键唯一的表,事实表里面一般存储这些维度的时候都是用代号去存储的,这样方便事实表不会过大,如果存储描述性的列,对应的数据表可能会变得很大。一般事实表用fact来表示,维度表用dim来表示,有些命名也不按照这个套路来也没关系,只是通用的一种命名方式。根据维度表和事实表的不同的关系,我们又把模型分为了星型模型和雪花模型,还有星座模型,星型模型就是一张事实表与很多维度表进行关联,可以得到一个数据的宽表,这里的维度表只是一层维度,就可以关联到我们想要的宽表,这就是很简单的星型模型,这种模型在维表里是不符合范式建模的,有数据冗余的,可以降低冗余拆分成更细粒度的维表,更加范式化的去建表,这个时候就形成了雪花模型,一张事实表和过渡维度表,再去和小的细粒度维度表去关联,才能拿到真正的维度列,这是雪花模型。星型模型在数据分析的时候效率非常高,但是有数据冗余,雪花模型分析效率由于关联很多表效率比较低,它的数据表存储的时候冗余相对比较少。
又说了维度建模的案例,分析出来哪些是事实表,哪些是维度表就可以了。数据仓库的分层,目的为了使数据更有秩序的去流转,做到以下这4点,清晰的数据结构,减少重复开发,统一数据出口,简化问题,有必要在数据处理的时候,在数据仓库里进行分层,除了以上这几点之外,Bill提出的CIF架构,也是结合了自上而下和自下而上构建数据仓库的优势,为了解决数据仓库分析效率的问题,以及数据不一致的问题,提出来一个CIF架构,这个架构建议在数据仓库里分不同的层,针对不同的层,使用不同的建模方式。
ODS层就是将源业务系统里的数据一对一的导入进来,这里的粒度保持一致,ODS层与关系型数据库里的表,这种建模方式是一致的,都是范式建模,到了DWD这一层,只是针对ODS层的数据,做相同数据的聚合,做数据质量的把控,做数据清洗,提供更干净的数据,更细粒度的数据,在DWD层了,它的粒度一般和ODS也是保持一致的,只是做一些数据空值的填补,数据的过滤,它的建模方式也是范式建模的方式。到了DWM这一层就是按照一些主题,通用的维度进行聚合,DWS是基于DWM,在DWM基础上再去进一步的按照主题,按照维度,进行聚合得到一个大宽表,DWS里面的数据,我们叫数据服务层,它服务的就是DM层数据集市,未来数据集市里面是面向主题域的,和业务强相关,业务报表数据都在这里面,有可能给机器学习部门去使用,可能给业务部门去使用,可能给APP就是web部门去使用,数据集市是面向不同部门的数据,它都是基于宽表去统计分析的报表数据,它的展示可以是以报表的方式去展现,或者以可视化方式,或者以接口的方式提供web用户去看也是可以的。
数据仓库分层的命名可能每个公司都有不同的方式,记住这几层,分别每一层做的事情就可以了。虽然理论方式不同,但这里分层每一层做的事情是一致的,只是名称上有所不同。
又提到了数据库与数据仓库的区别:
6个方面,数据范围,数据变化,应用场景,处理数据量,设计理论,建模方式
上节课提到的问题:
clickhouse和druid、kudu的应用场景
kudu的应用,hdfs里的数据存储起来,查询的时候,某一条数据是非常困难的去获取,我们想在分布式里存储数据,想精准的获取一条数据,可以在hbase中去存储,那hdfs对于随机的去读取支持不好,我们可以在hbase里对于随机的查询,可以很好的得到支持,但是hdfs有一个缺点,就是hdfs主要面向数据分析,在hive里做一个大批量的,时间周期比较长的数据分析,但是hbase面向的场景就是它的查询有缓存,它的查询速度非常快,这时候可以从hbase里很快的做到交互式的查询和更新数据,但hbase不支持写SQL,必须用api的方式去调用。这个kudu就介于两者之间,解决了两者的不足,kudu支持写SQL,它也相对于hbase时效性要低一些,也可以支持更新,相对于hdfs可以直接对数据做到随机性的访问,相当于做了两者兼容的一个技术。可以写SQL,可以分析,可以查询,分析时效性也是针对数据分析的场景,比hbase效率要低一些,比hdfs效率高一些。
clickhouse和druid经常用在流式计算场景里,druid主要存时序,和时间相关的数据,clickhouse更像是一个关系型数据库,它里面主要采用的是大量的索引来去解决查询速度的问题, 也有些公司用clickhouse做事实数仓,用flink这种流式框架去处理数据的结果可以放在clickhouse里面,或者druid,而kudu还是做批数据的分析。
今天开始正式介绍项目。
项目架构:
数据来源:用户的日志数据,原业务系统库1,原业务系统库2
为什么有两个原业务系统:有一些我们每日营收的情况的,机器的位置,活跃的用户,机器信息和商户信息的数据,商户的地址电话号码的数据,用户登陆的时候只能看到存放歌曲基本信息,展示热门歌曲榜单的业务库里的数据。
针对业务库的数据,我们是通过sqoop把原业务系统里的数据,增量或全量导入到数仓里面,用户日志数据就是运维人员每日上报数据。很多公司就是采用的这种人工智能的方式(人员操作的方式去处理数据)上报到HDFS里面,以压缩文件的方式,将日志文件从不同的节点上打包汇集在一起上传到HDFS平台,比如说规定1点之前要把数据上传好。
使用SparkCore+SparkSql清洗数据。把结果保存到数据仓库里面。
为什么不用hive去处理而使用sparkSql去处理呢?
spark速度要快,是正确的,spark处理速度比hive要快,hive里面要写udf,udaf函数的时候,spark也可以解决,hive也要做udf的编写,平平淡淡的只是写sql完成不了一些复杂的工作,这时候用sparksql就非常容易。对于复杂的场景写的代码量还是很多的。
数据仓库里面怎么分的层呢?
里面的业务不是特别复杂,只是分了三大层,第一层是ODS层,第二层是EDS层,第三层是DM层,这个ODS就是粒度和前面保持一一对应,EDS层就是做聚合分析,DM层做宽表结果的报表展示,这里的每一层之间的数据处理都是基于sparkSql去处理的,DM层数据的出口是MySQL数据库,有web接口(SpringBoot接口)的方式提供服务,给用户去使用的,有可视化工具报表展示,给内部人员去使用的。
这些整体都是批处理的过程。
流式数据的处理,用户登陆服务器,可能是多台服务器,每台服务器都会产生一些日志,应该把这些用户日志采集起来,每台节点部署flume,把这些日志采集在一起,通过avro的方式传递到一个节点,分布式日志采集,怎么把这些日志留下来呢?采用的是每个用户登陆之后,每个用户都会向服务器做一些请求,不管是登陆,点歌,点击广告,下线,都会做相应的请求,在做请求的时候,会把用户登陆的时间,用户号,点播的歌曲,请求点播的事件是什么,把这些日志分门别类的调用不同的日志接口,通过log4j写到对应的目录里面,搞一个springboot接口,用户调用不同的controller,后来叫做service,发现是什么类型的请求,通过log4j写到不同的目录里面,flume监控不同的目录,把它们采集起来。
flume采集的日志下一步到了Kafka中,Kafka中的数据用了spark streaming或者flilnk去处理流式业务,处理的结果也会放到一些数据库里面redis/mysql/hbase都是可以的,流式数据处理完的数据同样可以以接口的方式往外提供,也可以提供给可视化工具去展示。
或者将Kafka里的数据导入到hdfs里面,去构建类似实时的数仓也是可以的。 都是有可能的。
我们这个整体的项目调度的时候可能涉及到很多业务之间的流程是使用的Azkaban/Airflow进行任务流调度,资源调度是基于Yarn进行资源调度。
流式业务有些公司实时的场景非常少,就没必要去做实时业务,有实时业务场景的化可以去做,比如实时的展示一些结果报表,pv uv 简单的场景,做一个风控的实时监控,比如银行被刷走了钱,如果没有实时场景可以不需要实时。
分层的粒度如果业务真的是非常复杂,那把粒度分的细一些,很多公司做大数据仓库的分层,没有很好的做需求的分析,可能上来就简单的分层,真的有复杂的需求已经分析好了,哪一层哪一层做什么样的数据,这个时候可以设计的分层,比如哪些数据可以复用,可以多分一些层。
我们使用sparkSql可以直接写出到MySQL中的,不需要落地。
集群配置:
生产环境:集群有50台服务器,16核32线程+128G+40T。
20核40线程机器。32核64线程。56核112线程。
测试环境:5台测试机器,2核双线程+32G+1T磁盘
项目人数:
1个web人员(只做接口)+大数据开发4人(2人负责离线,1人负责实时,一人负责规划)+运维部门人员2人。
项目周期:
业务一直改变,目前2年。
数据量怎么计算:
比如有这种字段 2020-12-30 user001 www.baidu.com 111111111111 login 2020-12-30 444444 写了7个字段都是字符串,这个长度就是这么一个长度,大概是对应这么长的7个字段,1W条数据≈1M
按照你有多少个字段,每个字段是什么样的长度,去对比,统计一下1小时/一天导入过来的数据量有多少,能算出来每天数据的增量是多少。
pv uv的数据,以那个数据为例的,1W条数据=1M
服务器选的越大越好,会把最近半年或者一年的这种数据量预留计算出来,可能在这基础上,还会往后延个半年一年的,在选多少台服务器的时候,计算量和存储量都会往后预先的,把未来一年或者两年的数据,在选择集群的时候,把这种集群的规模会预先选择好,保证未来2~3年不增加机器台数。
这些机器都是用什么管理的呢?
开始用CDH或者Ambari(HDP)很多管理工具可以管理集群。
数据来源分为两类,业务库系统和用户日志数据,后期会一一导入进来,看项目怎么做。
数据仓库模型:命名的规范
数据仓库按照主题分为三个主题:用户、机器(位置、营收)、内容(歌曲相关、歌手相关)。每个主题下面都有对应的表。数据仓库的设计分为三层,如下:
ODS文件中是从业务数据库中抽取出来数据表的原数据, 数据从关系型数据库MySQL中导入,转换成Parquet格式的文件存在HDFS中,后期方便使用SparkSQL处理。
ODS层数据来源如下:
外部数据源:网易云爬取歌曲热度数据、歌手热度数据,爬取数据是json格式的数据。
内部数据源:主要有MySQL和客户端上传json数据。MySQL使用Sqoop抽取数据到HDFS中,导入ODS层。客户端产生日志到客户端服务器,客户端服务器由运维人员每天将数据压缩成包导入到HDFS路径中,也就是ODS层。
EDS层负责信息集成、轻度汇总类数据。简单理解就是将事务性的数据组织成便于分析的仓库维度建模类型的数据,做一些轻度聚合,类似Hive中的宽表。例如:将ODS层数据进行清洗,如果主题是用户主题,那么就按照用户id为粒度将数据组织在一起。如果主题是机器,那么就按照机器id为粒度将数据组织在一起。
以上ODS层和EDS层使用Spark代码处理数据,然后利用SparkSQL读取ODS层数据,保存到Hive的EDS层。
DM层的数据有一部分是存储在Hive表中,或者保存分析结果到MySQL、HBase等。EDS层数据是parquet格式的数据,放在Hive的主要原因是后期使用Kylin 查询一些业务,数据放MySQL的都是结果数据,放在HBase的原因是设涉及到大表的明细查询。
以上数据仓库模型的设计表对应关系都在“数据仓库模型.xlsx”文件中。
mark 1小时40分 继续更新…连看了两天指环王,我好喜欢这个系列
数据仓库分了这么多层,业务数据库表很多,日志数据的类别也很多,但是在ODS层或者EDS或者DM层里面,这些表,它的命名规范显得是非常重要的,因为要看到一张表,很直观的要知道这张表它表述的是什么内容,而不需要看它的数据我就知道这张表表达的什么内容这是最好的一种效果,这就是为什么数据仓库里面有一些命名规范的原因,不是层数而是表的规范也是有讲究的。这时候数据仓库里没一张表到底怎么去命名,这就是一个规范,来看一个通用的规范,在银行里是通用的,很多公司都是参照这种规范去设计的。。
表命名约定:
数据源:原业务系统里的数据源,数据来到数仓之前的,要么是业务系统里的数据,要么是日志数据,凡是开头是TO(ODS层中的一张表)的表,数据源、业务域、内容、周期我们都是使用下划线来隔开的,既然是ODS层,一定是有一个源头的数据的,后面要跟的就是数据源了,如果来自于YCAK这是我们一个原业务系统里面数据库的名称。TO_CLIENT来自于客户端日志的ODS层数据,如果是TW或者TM开头的就没有数据源了,就要跟业务域了,就是我们说的主题,我们又分了详细的,TW_MAC这张表是数据仓库那一层的数据,关于机器这个业务的,以主题命名也叫MAC,TM_MAC数据集市中关于机器的一张表。如果看到的是TW_USR是EDS层数据仓库的一张表,与用户相关的一张表。这是一种约定。
为什么都标的绿色,如果TO开头一定是来自于什么业务库,如果是其他TW或者TM开头的,后面跟的一定是业务相关,表描述的是什么内容主题。
接下来是更详细的内容描述,继续按照下划线隔开,假设有这么一张表TO_SONG_BASEINFO 数据源是SONG数据库,描述的歌曲基本信息。TM_MAC_CNT 数据集市层描述的是机器,里面是机器的信息,统计的机器的数量。可能一个字段描述不清,TW_MAC_CITY_LOC 可以在内容里使用更多下划线分隔这种字段来表示内容,建议不要超过3个字段。比如TW_USR_ACT_USR_CNT 是数据仓库层,关于用户底下的一张表,描述的是活跃用户的数量。
最后还有一个周期,比如TW_MAC_LOC_D 这张表每天更新一次,_W 每周更新一次,_M 每月更新一次。在实际业务场景中天和月使用的比较多。
数据分层命名约定:
主题域命名约定:
周期标准命名约定:
数据源命名约定:
业务需求:统计歌曲热度、歌手热度
用户可以登陆机器进行点播歌曲,根据用户过去每日在机器上的点播歌曲的情况,统计出最近1日、7日、30日歌曲热度和歌手热度。
需要统计的指标有:
1日歌曲热度
1日歌手热度
7日歌曲热度
7日歌手热度
30日歌曲热度
30日歌手热度
统计这些东西需要进行一个需求分析:
我们需要的数据:
1)需要用户每日点播的歌曲数据
用户点播歌曲的数据在哪里呢?currentday_clientlog.tr.gz 这个压缩文件,是运维人员将用户这些日志的数据,每日上报到hdfs里面来的数据,它就是以这种压缩包的方式来上报过来的,从每台机器上收集过来的日志文件,有5185个,给统一打包上传到平台里面,这每一个文件大小都不一样,可以看到文件数据长相是这个样子的:
文件示例:minik_jo_20191202235910_9541
1575302350&99712&MINIK_CLIENT_ADVERTISEMENT_RECORD&{"src_verison": 2546, "mid": 99712, "adv_type": 4, "src_type": 2546, "uid": 0, "session_id": 48565, "event_id": 1, "time": 1575302349}&3.0.1.15&2.4.4.30
1575302350&89316&MINIK_CLIENT_ADVERTISEMENT_RECORD&{"src_verison": 2565, "mid": 89316, "adv_type": 4, "src_type": 2565, "uid": 0, "session_id": 33762, "event_id": 1, "time": 1575302348}&3.0.1.12&2.4.4.26
1575302350&54398&MINIK_CLIENT_ADVERTISEMENT_RECORD&{"src_verison": 2546, "mid": 54398, "adv_type": 4, "src_type": 2546, "uid": 0, "session_id": 31432, "event_id": 1, "time": 1575302349}&3.0.1.14&2.4.4.30
1575302350&49120&MINIK_CLIENT_ADVERTISEMENT_RECORD&{"src_verison": 2546, "mid": 49120, "adv_type": 4, "src_type": 2546, "uid": 0, "session_id": 25078, "event_id": 1, "time": 1575302350}&3.0.1.15&2.4.4.30
1575302350&57563&MINIK_CLIENT_ADVERTISEMENT_RECORD&{"src_verison": 2571, "mid": 57563, "adv_type": 4, "src_type": 2571, "uid": 0, "session_id": 13577, "event_id": 1, "time": 1575302349}&3.0.1.15&2.4.4.30
分别解释一下这些字段:
上报的日志是经过一些处理的,把它采集过来,也是调接口写到对应的目录上,我们没有留就用人工打包的方式上传过来,每个字段分别什么意思?
时间戳,
对应的机器id,
客户在这个机器上进行了操作,这个操作的日志是请求点播歌曲的日志,还是请求点击广告的日志,还是请求播放歌曲列表的日志,还是进行开门扫码的请求 日志,有很多不同类型的请求,大概有72类,
json字符串,当前这个请求携带的参数数据,
版本,
当前机器上歌库的版本
ui的版本
我们要从日志里找到,到底哪些数据是用户进行的点播歌曲的请求?
还有个文件叫做事件上报协议,里面放的数据就是当前这个用户在点播歌曲的时候,事件是谁,
终端向服务器通知歌曲播放操作
MINIK_CLIENT_SONG_PLAY_OPERATE_REQ