文章目录
- 数据仓库概念
- 项目需求及架构设计
- 项目需求分析
- 系统数据流程设计
- 框架版本选型
- 集群规模估算
- 集群资源规划设计
- 数据生成模块
- 目标数据
- 页面
- 事件
- 曝光
- 启动
- 播放
- 错误
- 数据埋点
- 主流埋点方式(了解)
- 埋点数据上报时机
- 埋点数据日志结构
- 服务器和JDK准备
- 服务器准备
- 编写集群分发脚本xsync
- SSH无密登录配置
- JDK准备
- 环境变量配置说明
- 登录Shell和非登录Shell的区别
- 模拟数据
- 使用说明
- 集群日志及业务数据生成脚本
数据仓库概念
数据仓库( Data Warehouse ),是为企业制定决策,提供数据支持的。可以帮助企业改进业务流程、提高产品质量等。
数据仓库的输入数据通常包括:业务数据、用户行为数据和爬虫数据等
业务数据:就是各行业在处理事务过程中产生的数据。比如用户在网站中登录、下单、支付等过程中,需要和网站后台数据库进行增删改查交互,产生的数据就是业务数据。业务数据通常存储在MySQL、Oracle等数据库中。
用户行为数据:用户在使用产品过程中,通过埋点收集与客户端产品交互过程中产生的数据,并发往日志服务器进行保存。比如页面浏览、点击、停留、评论、点赞、收藏等。用户行为数据通常存储在日志文件中。
爬虫数据:通常是通过技术手段获取其他公司网站的数据。
项目需求及架构设计
项目需求分析
1)采集平台
(1)用户行为数据采集平台搭建
(2)业务数据采集平台搭建
2)离线需求
3)实时需求
系统数据流程设计
框架版本选型
集群规模估算
集群资源规划设计
下面是根据您提供的信息转换成的Markdown表格:
服务名称 | 子服务 | hadoop102 | hadoop103 | hadoop104 |
---|---|---|---|---|
hadoop102 | 服务器 | √ | - | - |
hadoop103 | 服务器 | - | √ | - |
hadoop104 | 服务器 | - | - | - |
HDFS | NameNode | √ | - | - |
HDFS | DataNode | √ | √ | √ |
HDFS | SecondaryNameNode | - | - | √ |
Yarn | NodeManager | √ | √ | √ |
Yarn | Resourcemanager | - | √ | - |
Zookeeper | Zookeeper Server | √ | √ | √ |
Flume(采集日志) | Flume | √ | √ | - |
Kafka | Kafka | √ | √ | √ |
Flume(消费Kafka日志) | Flume | - | - | √ |
Flume(消费Kafka业务) | Flume | - | - | √ |
Hive | √ | √ | √ | |
MySQL | MySQL | √ | - | - |
DataX | √ | √ | √ | |
Spark | √ | √ | √ | |
DolphinScheduler | ApiApplicationServer | √ | - | - |
DolphinScheduler | AlertServer | √ | - | - |
DolphinScheduler | MasterServer | √ | - | - |
DolphinScheduler | WorkerServer | √ | √ | √ |
DolphinScheduler | LoggerServer | √ | √ | √ |
Superset | Superset | √ | - | - |
服务数总计 | 16 | 11 | 12 |
数据生成模块
目标数据
我们要收集和分析的数据主要包括页面数据、事件数据、曝光数据、启动数据、播放数据和错误数据。
页面
页面数据主要记录一个页面的用户访问情况,包括访问时间、停留时间、页面路径等信息。
1)日志范例如下
{
"actions": [
…
],
"common": {
…
},
"displays": [
…
],
"page": {
"during_time": 11622,
"item": "57",
"item_type": "course_id",
"last_page_id": "course_list",
"page_id": "course_detail"
},
"ts": 1645529967261
}
2)所有页面类型如下:
home("首页")
course_list("列表页")
course_detail("商品详情")
chapter_video("章节视频")
cart("购物车")
order("下单结算")
payment("支付页面")
exam("考试")
mine("我的")
3)所有页面对象类型如下:
course_id("课程Id")
keyword("搜索关键词")
video_id("视频id")
chapter_id("章节id")
coupon_id("购物券id")
order_id("订单id")
paper_id("考卷id")
exam_id("考试id")
事件
事件数据主要记录应用内一个具体操作行为,包括操作类型、操作对象、操作对象描述等信息。
1)日志范例:
{
"actions": [
{
"action_id": "favor_add",
"item": "57",
"item_type": "course_id",
"ts": 1645529967261
},
{
"action_id": "cart_add",
"item": "57",
"item_type": "course_id",
"ts": 1645529967261
}
],
"common": {
…
},
"displays": [
…
],
"page": {
…
},
"ts": 1645529967261
}
注:对于下单、支付等业务数据,可从业务数据库获取。
2)所有动作类型如下
favor_add(新增收藏)
review_add(新增课程评价)
comment_add(新增章节评价)
cart_add(加购物车)
3)所有动作目标类型如下:
course_id("课程Id")
keyword("搜索关键词")
video_id("视频id")
chapter_id("章节id")
coupon_id("购物券id")
order_id("订单id")
paper_id("考卷id")
exam_id("考试id")
曝光
曝光数据主要记录页面所展示的内容,包括曝光对象,曝光类型等信息。
1)曝光日志范例:
{
"actions": [
…
],
"common": {
…
},
"displays": [
{
"display_type": "query",
"item": "6",
"item_type": "course_id",
"order": 1,
"pos_id": 4
},
{
"display_type": "query",
"item": "8",
"item_type": "course_id",
"order": 2,
"pos_id": 5
},
{
"display_type": "query",
"item": "1",
"item_type": "course_id",
"order": 3,
"pos_id": 4
},
{
"display_type": "query",
"item": "10",
"item_type": "course_id",
"order": 4,
"pos_id": 1
},
{
"display_type": "promotion",
"item": "4",
"item_type": "course_id",
"order": 5,
"pos_id": 4
},
{
"display_type": "promotion",
"item": "4",
"item_type": "course_id",
"order": 6,
"pos_id": 4
},
{
"display_type": "query",
"item": "9",
"item_type": "course_id",
"order": 7,
"pos_id": 1
}
],
"page": {
…
},
"ts": 1645529967261
}
2)所有曝光类型如下:
promotion("商品推广")
recommend("算法推荐商品")
query("查询结果商品")
activity("促销活动")
3)所有曝光对象类型如下:
course_id("课程Id")
keyword("搜索关键词")
video_id("视频id")
chapter_id("章节id")
coupon_id("购物券id")
order_id("订单id")
paper_id("考卷id")
exam_id("考试id")
启动
启动数据记录应用的启动信息。
1)启动日志范例:
{
"common": {
…
},
"start": {
"entry": "notice",
"first_open": 0,
"loading_time": 17970,
"open_ad_id": 20,
"open_ad_ms": 2876,
"open_ad_skip_ms": 0
},
"ts": 1645532980257
}
2)所有启动入口类型如下:
icon("图标"),
notice("通知"),
install("安装后启动");
播放
播放日志记录播放信息。
1)播放日志范例:
{
"appVideo": {
"play_sec": 19,
"video_id": "3904"
},
"common": {
…
},
"ts": 1645526307119
}
错误
错误数据记录应用使用过程中的错误信息,包括错误编号及错误信息。
上述五种日志都有可能包含错误信息,此处仅对 appVideo 的错误日志进行展示。
1)错误日志范例
{
"appVideo":{
…
},
"common":{
…
},
"err":{
"error_code":3485,
"msg":" Exception in thread \\ java.net.SocketTimeoutException\\n \\tat com.yudan.edu2021.mock.log.AppError.main(AppError.java:xxxxxx)"
},
"ts":1645538276217
}
数据埋点
主流埋点方式(了解)
目前主流的埋点方式,有代码埋点(前端/后端)、可视化埋点、全埋点三种。
- 代码埋点是通过调用埋点SDK函数,在需要埋点的业务逻辑功能位置调用接口,上报埋点数据。例如,我们对页面中的某个按钮埋点后,当这个按钮被点击时,可以在这个按钮对应的 OnClick 函数里面调用SDK提供的数据发送接口,来发送数据。
- 可视化埋点只需要研发人员集成采集 SDK,不需要写埋点代码,业务人员就可以通过访问分析平台的“圈选”功能,来“圈”出需要对用户行为进行捕捉的控件,并对该事件进行命名。圈选完毕后,这些配置会同步到各个用户的终端上,由采集 SDK 按照圈选的配置自动进行用户行为数据的采集和发送。
- 全埋点是通过在产品中嵌入SDK,前端自动采集页面上的全部用户行为事件,上报埋点数据,相当于做了一个统一的埋点。然后再通过界面配置哪些数据需要在系统里面进行分析。
埋点数据上报时机
埋点数据上报时机包括两种方式。
方式一,在离开该页面时,上传在这个页面产生的所有数据(页面、事件、曝光、错误等)。优点,批处理,减少了服务器接收数据压力。缺点,不是特别及时。
方式二,每个事件、动作、错误等,产生后,立即发送。优点,响应及时。缺点,对服务器接收数据压力比较大。
埋点数据日志结构
我们的日志结构大致可分为三类,一是普通页面埋点日志,二是启动日志,三是播放日志。
普通页面日志结构如下,每条日志包含了,当前页面的页面信息,所有事件(动作)、所有曝光信息以及错误信息。除此之外,还包含了一系列公共信息,包括设备信息,地理位置,应用信息等,即下边的common字段。
1)普通页面埋点日志格式
{
"actions": [
{
"action_id": "favor_add",
"item": "57",
"item_type": "course_id",
"ts": 1645529967261
},
{
"action_id": "cart_add",
"item": "57",
"item_type": "course_id",
"ts": 1645529967261
}
],
"common": {
"ar": "16",
"ba": "iPhone",
"ch": "Appstore",
"is_new": "1",--是否首日使用,首次使用的当日,该字段值为1,过了24:00,该字段置为0。
"md": "iPhone 8",
"mid": "mid_161",
"os": "iOS 13.3.1",
"sc": "2",
"sid": "9acef85b-067d-49f9-9520-a0dda943304e",
"uid": "272",
"vc": "v2.1.134"
},
"displays": [
{
"display_type": "query",
"item": "6",
"item_type": "course_id",
"order": 1,
"pos_id": 4
},
{
"display_type": "query",
"item": "8",
"item_type": "course_id",
"order": 2,
"pos_id": 5
},
{
"display_type": "query",
"item": "1",
"item_type": "course_id",
"order": 3,
"pos_id": 4
},
{
"display_type": "query",
"item": "10",
"item_type": "course_id",
"order": 4,
"pos_id": 1
},
{
"display_type": "promotion",
"item": "4",
"item_type": "course_id",
"order": 5,
"pos_id": 4
},
{
"display_type": "promotion",
"item": "4",
"item_type": "course_id",
"order": 6,
"pos_id": 4
},
{
"display_type": "query",
"item": "9",
"item_type": "course_id",
"order": 7,
"pos_id": 1
}
],
"page": {
"during_time": 11622,
"item": "57",
"item_type": "course_id",
"last_page_id": "course_list",
"page_id": "course_detail"
},
"err":{
"error_code":1359,
"msg":" Exception in thread \\ java.net.SocketTimeoutException\\n \\tat com.yudan.edu2021.mock.log.AppError.main(AppError.java:xxxxxx)"
},
"ts": 1645529967261
}
2)启动日志格式
启动日志结构相对简单,主要包含公共信息,启动信息和错误信息。
{
"common": {
"ar": "1",
"ba": "Redmi",
"ch": "wandoujia",
"is_new": "1",
"md": "Redmi k30",
"mid": "mid_356",
"os": "Android 11.0",
"sc": "2",
"sid": "76909678-abaf-41c4-916d-a0a72f546bc1",
"uid": "161",
"vc": "v2.1.134"
},
"start": {
"entry": "notice",
"first_open": 0,
"loading_time": 17970,
"open_ad_id": 20,
"open_ad_ms": 2876,
"open_ad_skip_ms": 0
},
"err":{
"error_code":2959,
"msg":" Exception in thread \\ java.net.SocketTimeoutException\\n \\tat com.yudan.edu2021.mock.log.AppError.main(AppError.java:xxxxxx)"
},
"ts": 1645532980257
}
3)播放日志
播放日志结构相对简单,主要包含公共信息,播放信息和错误信息。
{
"appVideo": {
"play_sec": 19,
"video_id": "3904"
},
"common": {
"ar": "4",
"ba": "Sumsung",
"ch": "oppo",
"is_new": "0",
"md": "Sumsung Galaxy S20",
"mid": "mid_253",
"os": "Android 11.0",
"sc": "1",
"sid": "47157c4a-4790-4b9a-a859-f0d36cd62a10",
"uid": "329",
"vc": "v2.1.134"
},
"err":{
"error_code":3485,
"msg":" Exception in thread \\ java.net.SocketTimeoutException\\n \\tat com.yudan.edu2021.mock.log.AppError.main(AppError.java:xxxxxx)"
},
"ts": 1645526307119
}
服务器和JDK准备
服务器准备
安装如下文档配置步骤,分别安装hadoop102、hadoop103、hadoop104三台主机。
具体配置链接
编写集群分发脚本xsync
1)xsync集群分发脚本
-
需求:循环复制文件到所有节点的相同目录下
-
需求分析
①rsync命令原始拷贝:
rsync -av /opt/module root@hadoop103:/opt/
②期望脚本:
xsync要同步的文件名称③说明:在/home/yudan/bin这个目录下存放的脚本,atguigu用户可以在系统任何地方直接执行。
-
脚本实现
①在用的家目录/home/atguigu下创建bin文件夹
[yudan@hadoop102 ~]$ mkdir bin
②在/home/yudan/bin目录下创建xsync文件,以便全局调用
[yudan@hadoop102 ~]$ cd /home/yudan/bin [yudan@hadoop102 ~]$ vim xsync
#!/bin/bash #1. 判断参数个数 if [ $# -lt 1 ] then echo Not Enough Arguement! exit; fi #2. 遍历集群所有机器 for host in hadoop102 hadoop103 hadoop104 do echo ==================== $host ==================== #3. 遍历所有目录,挨个发送 for file in $@ do #4 判断文件是否存在 if [ -e $file ] then #5. 获取父目录 pdir=$(cd -P $(dirname $file); pwd) #6. 获取当前文件的名称 fname=$(basename $file) ssh $host "mkdir -p $pdir" rsync -av $pdir/$fname $host:$pdir else echo $file does not exists! fi done done
③修改脚本xsync具有执行权限
[yudan@hadoop102 bin]$ chmod +x xsync
④测试脚本
[yudan@hadoop102 bin]$ xsync xsync
SSH无密登录配置
-
hadoop102上生成公钥和私钥:
[yudan@hadoop102 .ssh]$ ssh-keygen -t rsa
然后敲(三个回车),就会生成两个文件id_rsa(私钥)、id_rsa.pub(公钥)
-
将hadoop102公钥拷贝到要免密登录的目标机器上
[yudan@hadoop102 .ssh]$ ssh-copy-id hadoop102 [yudan@hadoop102 .ssh]$ ssh-copy-id hadoop103 [yudan@hadoop102 .ssh]$ ssh-copy-id hadoop104
-
hadoop103上生成公钥和私钥:
[yudan@hadoop103 .ssh]$ ssh-keygen -t rsa
然后敲(三个回车),就会生成两个文件id_rsa(私钥)、id_rsa.pub(公钥)
-
将hadoop103公钥拷贝到要免密登录的目标机器上
[yudan@hadoop103 .ssh]$ ssh-copy-id hadoop102 [yudan@hadoop103 .ssh]$ ssh-copy-id hadoop103 [yudan@hadoop103 .ssh]$ ssh-copy-id hadoop104
-
hadoop104上生成公钥和私钥:
[yudan@hadoop104 .ssh]$ ssh-keygen -t rsa
然后敲(三个回车),就会生成两个文件id_rsa(私钥)、id_rsa.pub(公钥)
-
将hadoop104公钥拷贝到要免密登录的目标机器上
[yudan@hadoop102 .ssh]$ ssh-copy-id hadoop102 [yudan@hadoop103 .ssh]$ ssh-copy-id hadoop103 [yudan@hadoop104 .ssh]$ ssh-copy-id hadoop104
JDK准备
-
卸载现有JDK(3台节点)
[yudan@hadoop102 opt]# sudo rpm -qa | grep -i java | xargs -n1 sudo rpm -e --nodeps [yudan@hadoop103 opt]# sudo rpm -qa | grep -i java | xargs -n1 sudo rpm -e --nodeps [yudan@hadoop104 opt]# sudo rpm -qa | grep -i java | xargs -n1 sudo rpm -e --nodeps
(1)rpm -qa:表示查询所有已经安装的软件包
(2)grep -i:表示过滤时不区分大小写
(3)xargs -n1:表示一次获取上次执行结果的一个值
(4)rpm -e --nodeps:表示卸载软件 -
将JDK导入到hadoop102的/opt/software文件夹下面
JDK安装包
链接: https://pan.baidu.com/s/1-bY0-GN85TJRhp-levcoSg?pwd=8ah6
提取码: 8ah6 -
在Linux系统下的opt目录中查看软件包是否导入成功
[yudan@hadoop102 software]# ls /opt/software/ 看到如下结果: jdk-8u212-linux-x64.tar.gz
-
解压JDK到/opt/module目录下
[yudan@hadoop102 software]# tar -zxvf jdk-8u212-linux-x64.tar.gz -C /opt/module/
-
配置JDK环境变量
-
新建/etc/profile.d/my_env.sh文件
[yudan@hadoop102 module]# sudo vim /etc/profile.d/my_env.sh #JAVA_HOME export JAVA_HOME=/opt/module/jdk1.8.0_212 export PATH=$PATH:$JAVA_HOME/bin
-
让环境变量生效
[yudan@hadoop102 software]$ source /etc/profile.d/my_env.sh
-
-
测试JDK是否安装成功
[yudan@hadoop102 module]# java -version 如果能看到以下结果、则Java正常安装 java version "1.8.0_212"
-
分发JDK
[yudan@hadoop102 module]$ xsync /opt/module/jdk1.8.0_212/
-
分发环境变量配置文件
[yudan@hadoop102 module]$ sudo /home/yudan/bin/xsync /etc/profile.d/my_env.sh -
分别在hadoop103、hadoop104上执行source
[yudan@hadoop103 module]$ source /etc/profile.d/my_env.sh [yudan@hadoop104 module]$ source /etc/profile.d/my_env.sh
环境变量配置说明
Linux的环境变量可在多个文件中配置,如/etc/profile,/etc/profile.d/*.sh,/.bashrc,/.bash_profile等,下面说明上述几个文件之间的关系和区别。
bash的运行模式可分为login shell和non-login shell。
例如,我们通过终端,输入用户名、密码,登录系统之后,得到就是一个login shell。而当我们执行以下命令ssh hadoop103 command,在hadoop103执行command的就是一个non-login shell。
登录Shell和非登录Shell的区别
这两种shell的主要区别在于,它们启动时会加载不同的配置文件,login shell启动时会加载/etc/profile,/.bash_profile,/.bashrc。non-login shell启动时会加载~/.bashrc。
模拟数据
使用说明
模拟数据生成文件地址
链接: https://pan.baidu.com/s/1ZYFLlkhI4JqvzugvySs_Sg
提取码: k93s
-
将application.yml、edu2021-mock-2022-06-18.jar、path.json、edu0222.sql、logback.xml上传到hadoop102的/opt/module/data_mocker目录下
创建applog路径
[yudan@hadoop102 module]$ mkdir /opt/module/data_mocker
-
需要安装配置MySQL
MySQL安装包
链接: https://pan.baidu.com/s/1Yov8DpOPaji58Axzp6VDWA?pwd=us87
提取码: us87(1)将MySQL安装文件拷贝到/opt/software
01_mysql-community-common-5.7.16-1.el7.x86_64.rpm 02_mysql-community-libs-5.7.16-1.el7.x86_64.rpm 03_mysql-community-libs-compat-5.7.16-1.el7.x86_64.rpm 04_mysql-community-client-5.7.16-1.el7.x86_64.rpm 05_mysql-community-server-5.7.16-1.el7.x86_64.rpm mysql-connector-java-5.1.27-bin.jar
(2)卸载自带的Mysql-libs(如果之前安装过MySQL,要全都卸载掉)
[yudan@hadoop102 software]$ rpm -qa | grep -i -E mysql\|mariadb | xargs -n1 sudo rpm -e --nodeps
(3)安装 MySQL 依赖
[yudan@hadoop102 software]$ sudo rpm -ivh 01_mysql-community-common-5.7.16-1.el7.x86_64.rpm [yudan@hadoop102 software]$ sudo rpm -ivh 02_mysql-community-libs-5.7.16-1.el7.x86_64.rpm [yudan@hadoop102 software]$ sudo rpm -ivh 03_mysql-community-libs-compat-5.7.16-1.el7.x86_64.rpm
(4)安装 mysql-client
[yudan@hadoop102 software]$ sudo rpm -ivh 04_mysql-community-client-5.7.16-1.el7.x86_64.rpm
(5)安装 mysql-server
[yudan@hadoop102 software]$ sudo rpm -ivh 05_mysql-community-server-5.7.16-1.el7.x86_64.rpm
注意:如果报如下错误,这是由于yum安装了旧版本的GPG keys所造成,从rpm版本4.1后,在安装或升级软件包时会自动检查软件包的签名。
warning: 05_mysql-community-server-5.7.16-1.el7.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY error: Failed dependencies: libaio.so.1()(64bit) is needed by mysql-community-server-5.7.16-1.el7.x86_64 解决办法 [yudan@hadoop102 software]$ sudo rpm -ivh 05_mysql-community-server-5.7.16-1.el7.x86_64.rpm --force --nodeps
(6)启动 MySQL
[yudan@hadoop102 software]$ sudo systemctl start mysqld
(7)查看 MySQL 密码
[yudan@hadoop102 software]$ sudo cat /var/log/mysqld.log | grep password
(8)配置只要是root用户 + 密码,在任何主机上都能登录MySQL数据库。
i)用刚刚查到的密码进入MySQL(如果报错,给密码加单引号) [yudan@hadoop102 software]$ mysql -uroot -p'password' ii)设置复杂密码(由于MySQL密码策略,此密码必须足够复杂) mysql> set password=password("Qs23=zs32"); iii)更改MySQL密码策略 mysql> set global validate_password_length=4; mysql> set global validate_password_policy=0; iv)设置简单好记的密码 mysql> set password=password("000000"); v)进入MySQL库 mysql> use mysql vi)查询user表 mysql> select user, host from user; vii)修改user表,把Host表内容修改为% mysql> update user set host="%" where user="root"; viii)刷新 mysql> flush privileges; ix)退出 mysql> quit;
-
需要安装配置MySQL
sql文件地址
通过网盘分享的文件:edu.sql
链接: https://pan.baidu.com/s/1gQ3z-boyI7aSaPC8t2Yz3A?pwd=fyxm
提取码: fyxm
(1)登录Navicat等连接MySQL工具,创建数据库edu
(2)在数据库edu下,运行edu.sql文件
集群日志及业务数据生成脚本
在hadoop102的/home/atguigu目录下创建bin目录,这样脚本可以在服务器的任何目录执行。
[yudan@hadoop102 ~]$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/yudan/.local/bin:/home/yudan/bin
1)在/home/yudan/bin目录下创建脚本mock.sh
[yudan@hadoop102 bin]$ vim mock.sh
2)在脚本中编写如下内容
#! /bin/bash
ssh hadoop102 "cd /opt/module/data_mocker/;java -jar edu2021-mock-2022-06-18.jar 1>/dev/null 2>&1 &"
3)修改脚本执行权限
[yudan@hadoop102 bin]$ chmod +x mock.sh
4)测试脚本
[yudan@hadoop102 module]$ mock.sh
5)在hadoop102的/opt/module/data_mocker/log目录上查看生成的数据
[yudan@hadoop102 log]$ ls
app.log