1 实验目的
基于前期对用户行为日志数据的理解,熟悉并练习真实企业中数据的采集流程。主要实验目标有:
- 业务背景问题领域 ER 模型设计;
- 选择合适的技术,设计并实现原始日志数据的实时增量收集(包括单数据源和多数据源、多粒度增量收集;
- 设计并实现原始日志数据的实时解析与结构化存储
2 实验环境和数据集
个人笔记本电脑、虚拟机软件:vmware 15 、putty、psftp、IDEA IDE
安装三台虚拟机,操作系统为centos7,均安装了kafka,Zookeeper,在cluster2上安装了MYSQL
软件包名 | 软件名称 | 版本 | 安装目录 |
---|---|---|---|
jdk-7u80-linux-x64.tar.gz | java软件开发工具包 | 1.7.80 | /usr/local/jdk1.7.0_80 |
mysql-5.6.37-linux-glibc2.12-x86_64.tar.gz | MySQL | 5.6.37 | /usr/local/mysql |
zookeeper-3.4.6.tar.gz | Zookeeper | 3.4.6 | /usr/local/zookeeper-3.4.6 |
kafka_2.10-0.8.2.1.tgz | Kafka | 2.10.-0.8.2.1 | /usr/local/kafka_2.10.-0.8.2.1 |
mysql-connector-java-5.1.43-bin.jar | MySQL JDBC驱动 | 5.1.43 | /usr/local/apache-hive-1.1.0-bin/lib/ |
数据集: 某中文 IT 技术社区用户行为日志数据
本课程所使用的数据集一由某中文 IT 技术社区提供,共包含 157,427 位用户在2015 年期间产生的多种类型的行为数据。 数据集基本统计信息如下:
数据集中用户编号为U0000001至U0157247,文档 编号为D0000001至D1000000。原始行为日志数据以文本文件的形式存储,其记录格式为:每一行代表一条日志记录,包含四个字段,依次为用户行为类型、用户编号、博客编号和行为产生时间,用\001 分开。其中用户行为类型包括:用户发表博客、用户浏览博客、用户评论博客用户对博客点赞、用户对博客点踩、用户收藏博客等六种用户行为。
3实验步骤
.31 设计用于存储结构化的用户行为日志数据的 MySQL ER 模型
下载的数据集中,数据库表模式已经设计好,包含六张表。本机使用navicat在cluster2上建表
create TABLE userbasic(Uid VARCHAR(10) not NULL PRIMARY key, Gender VARCHAR(10) not null,Status VARCHAR(10) not null,FollowNum VARCHAR(10) not null,FansNum VARCHAR(10) not null,FriendNum VARCHAR(10) not null);
create TABLE useredu(Uid VARCHAR(10) not NULL PRIMARY key, Degree VARCHAR(10),SchoolName VARCHAR(50),MajorStr VARCHAR(50),FOREIGN KEY(Uid) REFERENCES userbasic(Uid));
create TABLE userskill(Uid VARCHAR(10) not NULL PRIMARY key, SkillName VARCHAR(255) ,FOREIGN KEY(Uid) REFERENCES userbasic(Uid));
create TABLE userinterest(Uid VARCHAR(10) not NULL PRIMARY key, InterestName VARCHAR(255),FOREIGN KEY(Uid) REFERENCES userbasic(Uid));
create TABLE articleinfo(Aid VARCHAR(10) not NULL PRIMARY key, DiggCount VARCHAR(10) not null,BuryCount VARCHAR(10) not null,ViewCount VARCHAR(10) not null,CommentCount VARCHAR(10) not null,Type VARCHAR(10) not null,IsTop VARCHAR(10) not null,Status VARCHAR(10) not null);
create TABLE userbehavior(Uid VARCHAR(10) not NULL,Behavior VARCHAR(10) not NULL,Aid VARCHAR(10) not null,BehaviorTime VARCHAR(30) not null,PRIMARY KEY(Uid,Behavior,Aid,BehaviorTime),FOREIGN key(Uid) REFERENCES userbasic(Uid),FOREIGN key(Aid) REFERENCES articleinfo(Aid));
3.2 创建Kafka话题并尝试设置不同的分区数目
启动zookeeper集群,kafka集群
#在三台机器上分别
$ zkServer.sh start
$ kafka-server-start.sh /usr/local/kafka_2.10-0.8.2.1/config/server.properties &
kafka使用分区将topic的消息打散到多个分区分布保存在不同的broker上,实现了producer和consumer消息处理的高吞吐量。这里我们为每一个表创建一个 topic,设置不同的分区数
$ kafka-topics.sh --create --zookeeper cluster1:2181,cluster2:2181,cluster3:2181 --replication-factor 3 --partitions 3 --topic userbasic
$ kafka-topics.sh --create --zookeeper cluster1:2181,cluster2:2181,cluster3:2181 --replication-factor 3 --partitions 1 --topic useredu
$ kafka-topics.sh --create --zookeeper cluster1:2181,cluster2:2181,cluster3:2181 --replication-factor 3 --partitions 2 --topic userinterest
$ kafka-topics.sh --create --zookeeper cluster1:2181,cluster2:2181,cluster3:2181 --replication-factor 3 --partitions 1 --topic userskill
$ kafka-topics.sh --create --zookeeper cluster1:2181,cluster2:2181,cluster3:2181 --replication-factor 3 --partitions 2 --topic userbehavior
$ kafka-topics.sh --create --zookeeper cluster1:2181,cluster2:2181,cluster3:2181 --replication-factor 3 --partitions 3 --topic articleinfo
#查看topic列表
$ kafka-topics.sh --list --zookeeper cluster1:2181,cluster2:2181,cluster3:2181
#查看topic详细信息
$ kafka-topics.sh --describe --zookeeper cluster1:2181,cluster2:2181,cluster3:2181
3.3 kafka生产者
接下来在IDEA中进行编程,创建java工程。因为不知道具体用到哪些jar包,这里导入了kafka/lib目录下的所有jar包。三种生产者使用多线程thread类,来实现抓取时间间隔、数据源的设置。
3.3.1 模拟单数据源秒级(每秒一次)抓取的 Kafka 生产者
以userbasic topic为例,程序每秒读取一行源文件中的数据,并每秒给userbasic中发送一次消息
注意start()是Thread类中的,线程start()的入口就是run()
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import kafka.javaapi.producer.Producer;
import kafka.producer.KeyedMessage;
import kafka.producer.ProducerConfig;
import kafka.serializer.StringEncoder;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
public class kafkaProducer extends Thread{
private String topic;
public kafkaProducer(String topic){
super();
this.topic = topic;
}
//线程入口
public void run() {
Producer producer = createProducer();
int i=0;
String str = null;
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream("D:\\files\\2019-2020\\11数据仓库与大数据工程\\实验\\Datasets_1\\userBasic\\userBasic");
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
//BufferedReader可以按行读取文件
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
try {
while((str = bufferedReader.readLine()) != null){
i++;
System.out.println(str+"-------"+i);
producer.send(new KeyedMessage<String, String>(topic, str));
try {
//这里控制读取文件的间隔
TimeUnit.SECONDS.sleep(1