大数据项目之电商分析平台.docx
- 文档编号:7184555
- 上传时间:2023-01-21
- 格式:DOCX
- 页数:126
- 大小:2.15MB
大数据项目之电商分析平台.docx
《大数据项目之电商分析平台.docx》由会员分享,可在线阅读,更多相关《大数据项目之电商分析平台.docx(126页珍藏版)》请在冰豆网上搜索。
大数据项目之电商分析平台
大数据项目之电商分析系统
1项目框架
1.1项目概述
本项目来源于企业级电商网站的大数据统计分析平台,该平台以Spark框架为核心,对电商网站的日志进行离线和实时分析。
该大数据分析平台对电商网站的各种用户行为(访问行为、购物行为、广告点击行为等)进行分析,根据平台统计出来的数据,辅助公司中的PM(产品经理)、数据分析师以及管理人员分析现有产品的情况,并根据用户行为分析结果持续改进产品的设计,以及调整公司的战略和业务。
最终达到用大数据技术来帮助提升公司的业绩、营业额以及市场占有率的目标。
本项目使用了Spark技术生态栈中最常用的三个技术框架,SparkCore、Spark
现了包括用
SQL和SparkStreaming,进行离线计算和实时计算业务模块的开发。
实
户访问
session分析、页面单跳转化率统计、热门商品离线统计、广告流量实时统计
4个业务模块。
通过合理的将实际业务模块进行技术整合与改造,该项目几乎完全涵盖了SparkCore、SparkSQL和SparkStreaming这三个技术框架中大部分的功能点、知识点,学员对于Spark技术框架的理解将会在本项目中得到很大的提高。
图1-1Spark计数框架
1.1项目框架
1.1.1项目整体框架
图1-2项目整体框架
本项目分为离线分析系统与实时分析系统两大模块。
在离线分析系统中,我们将模拟业务数据写入Hive表中,离线分析系统从Hive中获取数据,并根据实际需求(用户访问Session分析、页面单跳转化率分析、各区域热门商品统计)对数据进行处理,最终将分析完毕的统计数据存储到MySQL的对应表格中。
在实时分析系统中,我们将模拟业务数据写入Kafka集群中,实时分析系统从Kafkabroker中获取数据,通过SparkStreaming的流式处理对广告点击流量进行实时分析,最终将统计结果存储到MySQL的对应表格中。
1.1.2离线日志采集宏观流程
图1-3离线日志采集宏观流程
1.1.3实时日志采集宏观流程
图1-4实时日志采集宏观流程
1.1.4离线/实时日志采集框架
图1-5离线/实时日志采集框架
图1-5是一个企业级的日志处理框架,这一框架实现了对日志信息进行采集、汇总、清洗、聚合、分析的完整过程,并将日志数据分别存储到了离线和实时数据处理模块中,使得分析系统可以通过离线和实时两个角度对数据进行分析统计,并根据统计结果指导业务平台的改良和优化。
1.2数据分析
1.2.1离线数据分析
1.user_visit_action
user_visit_action表,存放网站或者APP每天的点击流数据。
通俗地讲,就是用
户对网站/APP每点击一下,就会产生一条存放在这个表里面的数据。
图1-6user_visit_action表
user_visit_action表中的字段解析如表1-1所示:
表1-1user_visit_action表字段解析
字段名称
说明
date
日期,代表这个用户点击行为是在哪一天
发生的
user_id
用户ID,唯一地标识某个用户
session_id
SessionID,唯一地标识某个用户的一个访
问session
page_id
页面ID,点击了某些商品/品类,也可能是搜索了某个关键词,然后进入了某个页面,
页面的id
action_time
动作时间,这个点击行为发生的时间点
search_keyword
搜索关键词,如果用户执行的是一个搜索
行为,比如说在网站/app中,搜索了某个关键词,然后会跳转到商品列表页面;
click_category_id
点击品类ID,可能是在网站首页,点击了
某个品类(美食、电子设备、电脑)
click_product_id
点击商品ID,可能是在网站首页,或者是在商品列表页,点击了某个商品(比如呷哺
呷哺火锅XX路店3人套餐、iphone6s)
order_category_ids
下单品类ID,代表了可能将某些商品加入了购物车,然后一次性对购物车中的商品下了一个订单,这就代表了某次下单的行为中,有哪些商品品类,可能有6个商品,但是就
对应了2个品类,比如有3根火腿肠(食品
品类),3个电池(日用品品类)
order_product_ids
下单商品ID,某次下单,具体对哪些商品
下的订单
pay_category_ids
付款品类ID,对某个订单,或者某几个订单,进行了一次支付的行为,对应了哪些品
类
pay_product_ids
付款商品ID,支付行为下,对应的哪些具
体的商品
city_id
城市ID,代表该用户行为发生在哪个城市
2.user_info
user_info表,是一张普通的用户基本信息表;这张表中存放了网站/APP所有注册用户的基本信息。
图1-7user_info表
user_i表中的字段解析如表1-1所示:
表1-2user_info表字段解析
字段名称
说明
user_id
用户ID,唯一地标识某个用户
username
用户登录名
name
用户昵称或真实姓名
age
用户年龄
professional
用户职业
city
用户所在城市
sex
用户性别
3.product_info
product_info表,是一张普通的商品基本信息表;这张表中存放了网站/APP所有商品的基本信息。
图1-8product_info表
表1-3product_info表字段解析
字段名称
说明
proudct_id
商品ID,唯一地标识某个商品
product_name
商品名称
extend_info
额外信息,例如商品为自营商品还是第三
方商品
1.2.2在线数据分析
程序每5秒向Kafka集群写入数据,格式如下:
格式:
timestampprovincecityuseridadid
表1-4在线数据分析
字段名称
取值范围
timestamp
当前时间毫秒
userId
0–99
provice/city
1–9
((0L,"北京","北京"),(1L,"上海","上海"),(2L,"南京","江苏省
"),(3L,"广州","广东省"),(4L,"三亚","海南省"),(5L,"武汉","湖北省
"),(6L,"长沙","湖南省"),(7L,"西安","陕西省"),(8L,"成都","四川省
"),(9L,"哈尔滨","东北省"))
adid
0-19
1.3项目需求
图1-9需求概述
1.3.1用户访问session统计
用户在电商网站上,通常会有很多的访问行为,通常都是进入首页,然后可能点击首页上的一些商品,点击首页上的一些品类,也可能随时在搜索框里面搜索关键词,还可能将一些商品加入购物车,对购物车中的多个商品下订单,最后对订单中的多个商品进行支付。
用户的每一次操作,其实可以理解为一个action,在本项目中,我们关注点击、搜索、下单、支付这四个用户行为。
用户session,是在电商平台的角度定义的会话概念,指的就是,从用户第一次进入首页,session就开始了。
然后在一定时间范围内,直到最后操作完(可能做了几十次、甚至上百次操作),离开网站,关闭浏览器,或者长时间没有做操作,那么session就结束了。
以上用户在网站内的访问过程,就称之为一次session。
简单理解,session就是某一天某一个时间段内,某个用户对网站从打开/进入,到做了大量操作,到最后关闭浏览器。
的过程,就叫做session。
session实际上就是一个电商网站中最基本的数据和大数据。
那么面向消费者/
用户端的大数据分析(C端),最基本的就是面向用户访问行为/用户访问session
的分析。
该模块主要是对用户访问session进行统计分析,包括session聚合指标计算、按时间比例随机抽取session、获取每天点击、下单和购买排名前10的品类、并获取top10品类中排名前10的session。
该模块可以让产品经理、数据分析师以及企业管理层形象地看到各种条件下的具体用户行为以及统计指标,从而对公司的产品设计以及业务发展战略做出调整。
主要使用SparkCore实现。
1.3.2页面单跳转化率统计
该模块主要是计算关键页面之间的单步跳转转化率,涉及到页面切片算法以及页面流匹配算法。
该模块可以让产品经理、数据分析师以及企业管理层看到各个关键页面之间的转化率,从而对网页布局,进行更好的优化设计。
主要使用SparkCore实现。
1.3.3区域热门商品统计
该模块主要实现每天统计出各个区域的top3热门商品。
该模块可以让企业管理层看到电商平台在不同区域出售的商品的整体情况,从而对公司的商品相关的战略进行调整。
主要使用SparkSQL实现。
1.3.4广告流量实时统计
网站/app中经常会给第三方平台做广告,这也是一些互联网公司的核心收入来源;当广告位招商完成后,广告会在网站/app的某个广告位发布出去,当用户访问网站/app的时候,会看到相应位置的广告,此时,有些用户可能就会去点击那个广告。
我们要获取用户点击广告的行为,并针对这一行为进行计算和统计。
用户每次点击一个广告以后,会产生相应的埋点日志;在大数据实时统计系统中,会通过某些方式将数据写入到分布式消息队列中(Kafka)。
日志发送给后台web服务器(nginx),nginx将日志数据负载均衡到多个Tomcat服务器上,Tomcat服务器会不断将日志数据写入Tomcat日志文件中,写入后,就会被日志采集客户端(比如flumeagent)所采集,随后写入到消息队列中(kafka),我们的实时计算程序会从消息队列中(kafka)去实时地拉取数据,然后对数据进行实时的计算和统计。
这个模块的意义在于,让产品经理、高管可以实时地掌握到公司打的各种广告的投放效果。
以便于后期持续地对公司的广告投放相关的战略和策略,进行调整和优化;以期望获得最好的广告收益。
该模块负责实时统计公司的广告流量,包括广告展现流量和广告点击流量。
实现动态黑名单机制,以及黑名单过滤;实现滑动窗口内的各城市的广告展现流量和广告点击流量的统计;实现每个区域每个广告的点击流量实时统计;实现每个区域
top3点击量的广告的统计。
主要使用SparkStreaming实现。
2预备知识
2.1Scala
2.1.1Scala操作符
表2-1Scala操作符
操作符
说明
:
:
该方法被称为cons,意为构造,向队列的头部追加数据,创造新的列表。
用法为x:
:
list,其中x为加入到头部的元素,无论x是列表与否,它都只将成为新生成列表的第一个元素,也就是说新生成的列表长度为list的长度
+1(btw,x:
:
list等价于list.:
:
(x))
:
+
:
+方法用于在尾部追加元素
+:
+:
方法用于在头部追加元素,和:
:
很类似,但
是:
:
可以用于patternmatch,而+:
则不行
++
该方法用于连接两个集合
:
:
:
该方法只能用于连接两个List类型的集合
2.1.2拉链操作
valprices=List(5.0,20.0,9.95)
valquantities=List(10,2,1)
priceszipquantities
把一对集合A和B的包含的元素合成到一个集合中:
运行结果:
List[(Double,Int)]=List((5.0,10),(20.0,2),(9.95,1))
这个方法之所以叫“拉链(zip)”,是因为它就像拉链的齿状结构一样将两个集合结合在一起。
注意:
如果一个集合比另一个集合端,那么结果中的对偶数量和较短的那个集合的元素数量相同。
zipAll方法可以让你指定较短列表的缺省值。
zipWithIndex方法返回对偶的列表,其中每个对偶中第二个组成部分是每个元素的下标。
2.2SparkCore
2.2.1SparkRDD持久化
Spark非常重要的一个功能特性就是可以将RDD持久化在内存中,当对RDD执行持久化操作时,每个节点都会将自己操作的RDD的partition持久化到内存中,并且在之后对该RDD的反复使用中,直接使用内存的partition。
这样的话,对于针对一个RDD反复执行多个操作的场景,就只要对RDD计算一次即可,后面直接使用该RDD,而不需要反复计算多次该RDD。
巧妙使用RDD持久化,甚至在某些场景下,可以将Spark应用程序的性能提高
10倍。
对于迭代式算法和快速交互式应用来说,RDD持久化是非常重要的。
例如,读取一个有着数十万行数据的HDFS文件,形成linesRDD,这一读取过程会消耗大量时间,在count操作结束后,linesRDD会被丢弃,会被后续的数据覆盖,当第二次再次使用count时,又需要重新读取HDFS文件数据,再次形成新的
linesRDD,这回导致反复消耗大量时间,会严重降低系统性能。
RDD
,只要调用其
cache()
或者
如果在读取完成后将linesRDD缓存起来,那么下一次执行count操作时将会直接使用缓存起来的linesRDD,这会节省大量的时间。
要持久化一个
persist()方法即可。
在该RDD第
一次被计算出来时,就会直接缓存在每个节点中,而且Spark的持久化机制还是自动容错的,如果持久化的RDD的任何partition丢失了,那么Spark会自动通过其源RDD,使用transformation操作重新计算该partition。
cache()和persist()的区别在于,cache()是persist()的一种简化方式,cache()的底层就是调用的persist()的无参版本,同时就是调用persist(MEMORY_ONLY),将输入持久化到内存中。
如果需要从内存中清除缓存,那么可以使用unpersist()方法。
Spark自己也会在shuffle操作时,进行数据的持久化,比如写入磁盘,主要是为了在节点失败时,避免需要重新计算整个过程。
表2-2Spark持久化级别
持久化级别
含义
MEMORY_ONLY
以非序列化的Java对象的方式持久化在JVM内存中。
如果内存无法完全存储RDD所有的
partition,那么那些没有持久化的partition就会在
下一次需要使用它们的时候,重新被计算
MEMORY_AND_DISK
同上,但是当某些partition无法存储在内存中时,
会持久化到磁盘中。
下次需要使用这些partition
时,需要从磁盘上读取
MEMORY_ONLY_SER
同MEMORY_ONLY,但是会使用Java序列化方式,将Java对象序列化后进行持久化。
可以减少内存开销,但是需要进行反序列化,因此会加大
CPU开销
MEMORY_AND_DISK_SER
同MEMORY_AND_DISK,但是使用序列化方式
持久化Java对象
DISK_ONLY
使用非序列化Java对象的方式持久化,完全存
储到磁盘上
MEMORY_ONLY_2MEMORY_AND_DISK_2
等等
如果是尾部加了2的持久化级别,表示将持久化数据复用一份,保存到其他节点,从而在数据丢失时,不需要再次计算,只需要使用备份数据
即可
以下为对一个156万行大小为168MB的文本文件进行处理,textFile后只进行
count操作,持久化与不持久化的结果如下:
2.2.3Spark共享变量
Spark一个非常重要的特性就是共享变量。
默认情况下,如果在一个算子的函数中使用到了某个外部的变量,那么这个变量的值会被拷贝到每个task中,此时每个task只能操作自己的那份变量副本。
如果多个task想要共享某个变量,那么这种方式是做不到的。
Spark为此提供了两种共享变量,一种是BroadcastVariable(广播变量),另一种是Accumulator(累加变量)。
BroadcastVariable会将用到的变量,仅仅为每个节点拷贝一份,更大的用途是优化性能,减少网络传输以及内存损耗。
Accumulator则可以让多个task共同操作一份变量,主要可以进行累加操作。
BroadcastVariable是共享读变量,task不能去修改它,而Accumulator可以让多个task操作一个变量。
1.广播变量
广播变量允许程序员在每个机器上保留缓存的只读变量,而不是给每个任务发送一个副本。
例如,可以使用它们以有效的方式为每个节点提供一个大型输入数据集的副本。
Spark还尝试使用高效的广播算法分发广播变量,以降低通信成本。
Sparkaction被划分为多个Stages,被多个“shuffle”操作(宽依赖)所分割。
Spark自动广播每个阶段任务所需的公共数据(一个Stage中多个task使用的数据),以这种方式广播的数据以序列化形式缓存,并在运行每个任务之前反序列化。
这意味着,显式创建广播变量仅在跨多个阶段的任务需要相同数据或者以反序列化格式缓存数据很重要时才有用。
Spark提供的BroadcastVariable是只读的,并且在每个节点上只会有一个副本,而不会为每个task都拷贝一份副本,因此,它的最大作用,就是减少变量到各个节点的网络传输消耗,以及在各个节点上的内存消耗。
此外,Spark内部也使用了高效的广播算法来减少网络消耗。
可以通过调用SparkContext的broadcast()方法来针对每个变量创建广播变量。
然后在算子的函数内,使用到广播变量时,每个节点只会拷贝一份副本了,每个节点可以使用广播变量的value()方法获取值。
2.累加器
累加器(accumulator):
Accumulator是仅仅被相关操作累加的变量,因此可以在并行中被有效地支持。
它们可用于实现计数器(如MapReduce)或总和计数。
Accumulator是存在于Driver端的,从节点不断把值发到Driver端,在Driver端计数(SparkUI在SparkContext创建时被创建,即在Driver端被创建,因此它可以读取Accumulator的数值),存在于Driver端的一个值,从节点是读取不到的。
Spark提供的Accumulator主要用于多个节点对一个变量进行共享性的操作。
Accumulator只提供了累加的功能,但是却给我们提供了多个task对于同一个变量并行操作的功能,但是task只能对Accumulator进行累加操作,不能读取它的值,只有Driver程序可以读取Accumulator的值。
自定义累加器类型的功能在1.X版本中就已经提供了,但是使用起来比较麻烦,在2.0版本后,累加器的易用性有了较大的改进,而且官方还提供了一个新的抽象类:
AccumulatorV2来提供更加友好的自定义类型累加器的实现方式。
官方同时给出了一个实现的示例:
CollectionAccumulator类,这个类允许以集合的形式收集spark应用执行过程中的一些信息。
例如,我们可以用这个类收集Spark处理数据时的一些细节,当然,由于累加器的值最终要汇聚到driver端,为了避免
driver端的outofmemory问题,需要对收集的信息的规模要加以控制,不宜过大。
classSessionAggrStatAccumulatorextendsAccumulatorV2[String,mutable.HashMap[String,Int]]{
//保存所有聚合数据
privatevalaggrStatMap=mutable.HashMap[String,Int]()
//判断是否为初始值
代码清单2-1自定义AccumulatorV2
2.3
overridedefisZero:
Boolean={aggrStatMap.isEmpty
}
//复制累加器
overridedefcopy():
AccumulatorV2[String,mutable.HashMap[String,Int]]={valnewAcc=newSessionAggrStatAccumulator
aggrStatMap.synchronized{newAcc.aggrStatMap++=this.aggrStatMap
}
newAcc
}
//重置累加器中的值
overridedefreset():
Unit={aggrStatMap.clear()
}
//向累加器中添加另一个值
overridedefadd(v:
String):
Unit={if(!
aggrStatMap.contains(v))
aggrStatMap+=(v->0)aggrStatMap.update(v,aggrStatMap(v)+1)
}
//各个task的累加器进行合并的方法
//合并另一个类型相同的累加器
overridedefmerge(other:
AccumulatorV2[String,mutable.HashMap[String,Int]]):
Unit=
{
othermatch{
caseacc:
SessionAggrStatAccumulator=>{
(this.aggrStatMap/:
acc.value){case(map,(k,v))=>map+=(k->(v+map.getOrElse(k,
0)))}
}
}
}
//获取累加器中的值
//AccumulatorV2对外访问的数据结果
overridedefvalue:
mutable.HashMap[String,Int]={this.aggrStatMap
}
}
SparkSQL
2.3.1RDD、DataFrame与DataSet
1.RDD
RDD,全称为ResilientDistributedDatasets,即分布式数据集,是Spark中最基本的数据抽象,它
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据 项目 分析 平台