出行大数据一
1、项目概述
-
随着人们对出行的需求日益增加,出行的安全问题,出行的便捷问题等问题日益突出,特别是安全出行是我们每个人都迫切需要的,为了增加出行的编辑,提高出行的安全,对我们乘车的细节以及发生点我们迫切的需要及时知道,为此特地通过大数据的手段来处理我们海量的出行数据。
-
做到:
- 订单的实时监控,
- 乘车轨迹的的细节回放,
- 虚拟车站的科学制定,
- 出行迁途的细节过程,
- 订单报表的大屏展示,
- 用户乘车行为统计
- 用户画像等功能,
实现用户的出行统计,制定用户的的“杀熟”策略等。
2、技术架构选型
数据主要分为两部分:
- 第一部分为日志数据,主要是司机端APP每隔一定时间上报经纬度坐标信息,以日志数据的形式进行打印到日志服务器。
- 第二部分数据为业务库数据,主要是存储在mysql,通过分库的形式将各个不同城市的数据存储在不同的业务库里面。
2.1、数据采集功能如何技术选型
数据采集框架很多,包括sqoop, datax, flume, logstash, maxwell, canal等各种数据采集框架适用场景不同,功能描述如以下表格。
采集框架名称 | 主要功能 |
---|---|
Sqoop | 大数据平台和关系型数据库的导入导出 |
datax | 大数据平台和关系型数据库的导入导出 |
flume | 擅长日志数据的采集和解析 |
logstash | 擅长日志数据的采集和解析 |
maxwell | 常用作实时解析mysql的binlog数据 |
canal | 常用作实时解析mysql的binlog数据 |
2.2、消息中间件的技术选型
市面上成熟的消息中间件技术框架也有很多,主要有以下各种消息中间件
开源MQ | 概述 |
---|---|
1.RabbitMQ | LShift 用Erlang实现,支持多协议,broker架构,重量级 |
2.ZeroMQ | AMQP最初设计者iMatix公司实现,轻量消息内核,无broker设计。C++实现 |
3.Jafka/Kafka | LinkedIn用Scala语言实现,支持hadoop数据并行加载 |
4.ActiveMQ | Apach的一种JMS具体实现,支持代理和p2p部署。支持多协议。Java实现 |
5.Redis | Key-value NoSQL数据库,有MQ的功能 |
6.MemcacheQ | 国人利用memcache缓冲队列协议开发的消息队列,C/C++实现 |
2.3、实时流式处理技术选型
流式处理技术已经非常成熟,且各大框架都有提供很多种选择,以下是各种流式处理技术选型技术对比
框架名称 | 框架介绍 |
---|---|
Storm | Twitter公司开源提供,早期的流失计算框架,基本已经退出大数据的舞台 |
SparkStreaming | 当下最火热的流失处理技术之一 |
Flink | 流式计算 |
Blink 流式计算 | 阿里二次开发的Flink框架 |
2.4、数据永久存储技术框架选型
数据永久存储框架也有很多,比较常见的例如Hbase,kudu,HDFS等
框架名称 | 主要用途 |
---|---|
HDFS | 分布式文件存储系统 |
Hbase | Key,value对的nosql数据库 |
Kudu | Cloudera公司开源提供的类似于Hbase的数据存储 |
2.5、数据离线计算框架技术选型
离线统计的框架也非常多,主要就是基于各种OLAP场景的应用计算
框架名称 | 基本介绍 |
---|---|
MapReduce | 最早期的分布式文件计算系统 |
hive | 基于MR的数据仓库工具 |
impala | 号称当前大数据领域最快的sql on hadoop框架,内存消耗特别大 |
SparkSQL | 基于spark,一站式解决批流处理问题 |
FlinkSQL | 基于flink,一站式解决批流处理问题 |
druid | 针对时间序列数据提供低延迟的数据写入以及快速交互式查询的分布式OLAP数据库 |
kylin | 基于Hbase实现的预计算 |
presto | 分布式SQL查询引擎,用于查询分布在一个或多个不同数据源中的大数据集 |
clickHouse | 俄罗斯开源提供的一个OLAP分析框架 |
3、日志数据格式说明
现在主要用到成都数据以及海口数据,针对成都以及海口数据字段说明如下
成都轨迹数据格式说明:一共5个字段
一共五个字段,字段详情参见下表,字段之间使用逗号隔开。
注意:上区域的中所体现的OD数据是相比全城是很小的量,不能反映全城的供需情况
目前得到的轨迹数据中可以看到时间不是按照递增的方式进行排列,在进行数据处理时需要先对数据按照时间进行升序排列(轨迹点的产生的时间是递增的,从时间的角度才能看出轨迹的运行规律),排序后便于在地图上进行轨迹的呈现.
海口订单数据格式说明:一共24个字段
海口订单数据一共24个字段,字段之间使用\t制表符分开,字段详情参见下表
开放城市:海口
开放范围:2017年5月1日 - 2017年10月31日
数据内容:上述时间范围内的海口市每天订单数据,包含订单的起终点经纬度以及订单类型、出行品类、乘车人数的订单属性数据。其中所有涉及个人信息的数据都经过了匿名化处理。
- 保留起终点经纬度小数点后四位,可能导致与真实环境坐标存在偏差,误差范围大概在十几米到几十米左右。
- 针对独门独户上下车点进行技术脱敏处理,将上下车点漂移到小区门口或街道上。
4、项目构建
-
1、 构建父工程travel项目
- 第一步:创建maven父工程travel,
创建maven顶级父工程travel,并导入jar包
- 第一步:创建maven父工程travel,
-
2、构建子模块travel_common模块,用于存放工具类
-
第一步:创建common模块,用于存放工具类
-
第二步:travel_common模块添加maven依赖坐标
在travel_common模块下添加坐标依赖 -
第三步:travel_common模块添加相应工具类
将java以及scala以及config.properties等相应工具类拷贝到travel_common模块当中去 -
第四步:更改config.properties当中的IP地址
将config.properties当中的IP地址全部更改替换成为自己的对应的IP地址
-
-
3、构建travel-web模块
继续构建我们的travel-web模块用于展示我们的web界面- 第一步:在父工程下面添加子模块travel_web
在travel父工程下面构建travel_web子模块 - 第二步:添加pom.xml坐标
- 第三步:拷贝资源文件以及web模块代码
将我们附件当中的资源文件以及web模块的代码拷贝到工程当中来
将我们的静态资源页面拷贝到resources路径下 - 第四步:启动travel_web项目并访问
构建好的travel_web项目主要是用于我们的数据界面展示,我们可以启动web模块,并访问页面
- 第一步:在父工程下面添加子模块travel_web
-
4、构建travel_spark模块
- 构建travel_spark子模块,用于实现首页概览,订单监控,轨迹监控,虚拟车站,用户数据,热力图等功能模块的开发
- 第一步:在父工程travel下面添加子模块travel_spark
- 第二步:添加pom.xml坐标依赖
- 第三步:拷贝资源文件夹以及scala和java辅助代码
- 将我们的辅助代码拷贝到对应的目录下,将对应的java代码,scala代码以及对应的目录下
5、日志数据回放模块
通过回放我们的成都以及海口数据,使用flume采集我们的日志数据,然后将数据放入到kafka当中去,通过sparkStreaming消费我们的kafka当中的数据,然后将数据保存到hbase,并且将海口数据保存到redis当中去,实现实时轨迹监控以及历史轨迹回放的功能
为了模拟数据的实时生成,我们可以通过数据回放程序来实现订单数据的回放功能,主要数据参见课件当中的数据,我们这里主要使用到了成都以及海口的数据来实现数据的回放
第一步:上传数据到服务器
将海口数据上传到node01服务器的/kkb/datas/sourcefile
这个路径下
node01执行以下命令创建文件夹,然后上传数据
mkdir -p /kkb/datas/sourcefile
将成都数据上传到node02服务器的/kkb/datas/sorucefile
这个路径下
node02执行以下命令创建文件夹,然后上传数据
mkdir -p /kkb/datas/sourcefile
第二步:通过脚本回放数据
使用课件当中的FileOperate-1.0-SNAPSHOT-jar-with-dependencies.jar
这个jar包来实现数据的读取然后写入到另外一个文件当中去
将FileOperate-1.0-SNAPSHOT-jar-with-dependencies.jar
这个jar包上传到node01服务器的/home/hadoop
路径下去
在node01服务器的/home/hadoop/bin路径下创建shell脚本,用于数据的回放
cd /home/hadoop/bin
vim start_stop_generate_data.sh
#!/bin/bash
scp /home/hadoop/FileOperate-1.0-SNAPSHOT-jar-with-dependencies.jar node02:/home/hadoop/
#休眠时间控制
sleepTime=1000
if [ ! -n "$2" ];then
echo ""
else
sleepTime=$2
fi
case $1 in
"start" ){
for i in node01 node02
do
echo "-----------$i启动数据回放--------------"
ssh $i "source /etc/profile;nohup java -jar /home/hadoop/FileOperate-1.0-SNAPSHOT-jar-with-dependencies.jar /kkb/datas/sourcefile /kkb/datas/destfile $2 > /dev/null 2>&1 & "
done
};;
"stop"){
for i in node02 node01
do
echo "-----------停止 $i 数据回放-------------"
ssh $i "source /etc/profile; ps -ef | grep FileOperate-1.0-SNAPSHOT-jar | grep -v grep |awk '{print \$2}' | xargs kill"
done
};;
esac
给脚本赋予执行权限
cd /home/hadoop/bin
chmod 777 start_stop_generate_data.sh
第三步:通过flume来采集数据
node01开发flume的配置文件
cd /kkb/install/apache-flume-1.6.0-cdh5.14.2-bin/conf/
vim flume_client.conf
a1.sources = r1
a1.sinks = k1
a1.channels = c1
# Describe/configure the source
#配置source
a1.sources.r1.type = taildir
a1.sources.r1.positionFile = /kkb/datas/flume_temp/flume_posit/haikou.json
a1.sources.r1.filegroups = f1
a1.sources.r1.filegroups.f1 = /kkb/datas/destfile/part.+
a1.sources.r1.fileHeader = true
a1.sources.r1.channels = c1
a1.sources.r1.interceptors = i1
a1.sources.r1.interceptors.i1.type = static
## static拦截器的功能就是往采集到的数据的header中插入自己定## 义的key-value对
a1.sources.r1.interceptors.i1.key = type
a1.sources.r1.interceptors.i1.value = hai_kou_gps_topic
#flume监听轨迹文件内容的变化 tuch gps
#配置sink
#a1.sinks.k1.type = org.apache.flume.sink.kafka.KafkaSink
#flume监听的文件数据发送到此kafka的主题当中
#a1.sinks.k1.topic = hai_kou_gps_topic
#a1.sinks.k1.brokerList= node01:9092,node02:9092,node03:9092
#a1.sinks.k1.batchSize = 20
#a1.sinks.k1.requiredAcks = 1
#a1.sinks.k1.producer.linger.ms = 1
#配置sink
a1.sinks.k1.type = avro
a1.sinks.k1.hostname = node03
a1.sinks.k1.port = 41414
#配置channel
a1.channels.c1.type = file
#检查点文件目录
a1.channels.c1.checkpointDir=/kkb/datas/flume_temp/flume_check
#缓存数据文件夹
a1.channels.c1.dataDirs=/kkb/datas/flume_temp/flume_cache
# Bind the source and sink to the channel
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
node02开发flume的配置文件
cd /kkb/install/apache-flume-1.6.0-cdh5.14.2-bin/conf/
vim flume_client.conf
a1.sources = r1
a1.sinks = k1
a1.channels = c1
# Describe/configure the source
#配置source
a1.sources.r1.type = taildir
a1.sources.r1.positionFile = /kkb/datas/flume_temp/flume_posit/chengdu.json
a1.sources.r1.filegroups = f1
a1.sources.r1.filegroups.f1 = /kkb/datas/destfile/part.+
a1.sources.r1.fileHeader = true
a1.sources.r1.channels = c1
a1.sources.r1.interceptors = i1
a1.sources.r1.interceptors.i1.type = static
## static拦截器的功能就是往采集到的数据的header中插入自己定## 义的key-value对
a1.sources.r1.interceptors.i1.key = type
a1.sources.r1.interceptors.i1.value = cheng_du_gps_topic
#flume监听轨迹文件内容的变化 tuch gps
#配置sink
#a1.sinks.k1.type = org.apache.flume.sink.kafka.KafkaSink
#flume监听的文件数据发送到此kafka的主题当中
#a1.sinks.k1.topic = cheng_du_gps_topic
#a1.sinks.k1.brokerList= node01:9092,node02:9092,node03:9092
#a1.sinks.k1.batchSize = 20
#a1.sinks.k1.requiredAcks = 1
#a1.sinks.k1.producer.linger.ms = 1
a1.sinks.k1.type = avro
a1.sinks.k1.hostname = node03
a1.sinks.k1.port = 41414
#配置channel
a1.channels.c1.type = file
#检查点文件目录
a1.channels.c1.checkpointDir=/kkb/datas/flume_temp/flume_check
#缓存数据文件夹
a1.channels.c1.dataDirs=/kkb/datas/flume_temp/flume_cache
# Bind the source and sink to the channel
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
node03开发flume的配置文件
cd /kkb/install/apache-flume-1.6.0-cdh5.14.2-bin/conf/
vim flume2kafka.conf
a1.sources = r1
a1.sinks = k1
a1.channels = c1
#定义source
a1.sources.r1.type = avro
a1.sources.r1