查看历史记录的命令
history | grep kafka
以下是RNG S8 8强赛失败后,官微发表道歉微博下一级评论
数据说明:
rng_comment.txt
文件中的数据
字段 | 字段含义 |
---|---|
index | 数据id |
child_comment | 回复数量 |
comment_time | 评论时间 |
content | 评论内容 |
da_v | 微博个人认证 |
like_status | 赞 |
pic | 图片评论url |
user_id | 微博用户id |
user_name | 微博用户名 |
vip_rank | 微博会员等级 |
stamp | 时间戳 |
1.1、在kafak中创建rng_comment
主题,设置2
个分区2
个副本
1.2、数据预处理,把空行
过滤掉
1.3、请把给出的文件写入到kafka
中,根据数据id
进行分区,id为奇数
的发送到一个分区中,偶数
的发送到另一个分区
1.5、使用Spark Streaming对接kafka之后进行计算
- 在mysql中创建一个数据库
rng_comment
[root@node01 /]# mysql -uroot -p123456
mysql>create databases rng_comment;
//切换
mysql>use rng_comment;
//查看表
mysql>show tables;
- 在数据库
rng_comment
创建vip_rank
表,字段为数据的所有字段
create table vip_rank(
Indexx varchar(255) NOT NULL,
child_comment varchar(255) NOT NULL,
comment_time varchar(255) NOT NULL,
content varchar(255) NOT NULL,
da_v varchar(255) NOT NULL,
like_status varchar(255) NOT NULL,
pic varchar(255) NOT NULL,
user_id varchar(255) NOT NULL,
user_name varchar(255) NOT NULL,
vip_rank varchar(255) NOT NULL,
stamp varchar(255) NOT NULL,
PRIMARY KEY (‘indexx’)
)ENGINE=InnoDB AUTO_TNCREMENT=26 DEFAULT CHARSET=udf8;
- 在数据库
rng_comment
创建like_status
表,字段为数据的所有字段
- 在数据库
rng_comment
创建count_conmment
表,字段为 时间,条数
1.5.1、查询出微博会员等级为5的用户,并把这些数据写入到mysql数据库中的vip_rank表中
1.5.2、查询出评论赞的个数在10个以上的数据,并写入到mysql数据库中的like_status表中
1.5.3、分别计算出2018/10/20 ,2018/10/21,2018/10/22,2018/10/23这四天每一天的评论数是多少,并写入到mysql数据库中的count_conmment表中
数据如下👇
数据过大,所以放到百度云上,失效请私信博主!
链接: https://pan.baidu.com/s/1jMsJbN9RLh5ItXFDXdwVjw 提取码: 1234
数据预处理,取出空行
package com.Job414.Job
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.{DataFrame, SparkSession}
import org.apache.spark.{SparkConf, SparkContext}
object FilterNull {
def main(args: Array[String]): Unit = {
//处理数据的思路
//1.2 需求:数据预处理,把空行过滤掉
/*
1 读取数据
2 处理数据
如果数据为空就删除掉,反之,就保留数据
3写出数据
*/
val spark: SparkSession = SparkSession.builder().appName("FilterNull").master("local").getOrCreate()
//设置sparkcontext,用于读取数据
var sc =spark.sparkContext
//读取数据
//txtFile是多有数据
val txtFile: RDD[String] = sc.textFile("F:\\网课\\Spark\\spark练习\\4.14号练习题\\rng_comment.txt")
//过滤数据
val datas: RDD[String] = txtFile.filter(a => {
//filter保留true数据
//数据不为空返回true 表示要保留
if (a != "\t\t\t\t\t\t\t\t\t\t") {
true
} else {
//数据为空返回false 表示要删除
false
}
/* if (a.trim != "") {
true
} else {
//数据为空返回false 表示要删除
false
}*/
})
//为了使用DF对象将数据输出,所以需要将rdd转为DF
//RDD -> DF
import spark.implicits._
//3写出数据
val dataDF: DataFrame = datas.toDF()
dataDF.repartition(1).write.text("F:\\网课\\Spark\\spark练习\\4.14号练习题\\tmp")
sc.stop()
spark.stop()
}
}
读取数据写入Kafka
package com.Job414.Job;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.Properties;
public class TxtToKafka {
public static void main(String[] args) throws Exception {
//kafka环境配置
//1、配置kafka集群环境(设置)
Properties props = new Properties();
//kafka服务器地址
props.put("bootstrap.servers", "node01:9092,node02:9092,node03:9092");
//消息确认机制
props.put("acks", "all");
//重试机制
props.put("retries", 0);
//批量发送的大小
props.put("batch.size", 16384);
//消息延迟
props.put("linger.ms", 1);
//批量的缓冲区大小
props.put("buffer.memory", 33554432);
// kafka key 和value的序列化
props.put("key.serializer","org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer","org.apache.kafka.common.serialization.StringSerializer");
props.put("partitioner.class", "Job.newPartition");
//2、 将不为空的数据写入kafka
//写aa 数据到kafka
KafkaProducer<String, String> kafkaProducer = new KafkaProducer<String, String>(props);
//使用java 读取本地文件,按行读取,数据写入kafka时按行每行写入一次
//1、
File file=new File("F:\\网课\\Spark\\spark练习\\4.14号练习题\\rng_comment.txt");
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
String line=null;
//获取每条数据
while((line=bufferedReader.readLine())!=null){
if (!line.equals("\t\t\t\t\t\t\t\t\t\t")){
kafkaProducer.send(new ProducerRecord<>("18BD12",line));
System.out.println(line);
Thread.sleep(100);
}
}
kafkaProducer.close();
//3、 数据分区
//自定义
//添加到kafka的配置文件中
}
}
package com.Job414.Job;
import org.apache.kafka.clients.producer.Partitioner;
import org.apache.kafka.common.Cluster;
import java.util.Map;
//3、 数据分区
public class newPartition implements Partitioner {
//自定义分区代码块
@Override
public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
//根据数据id进行分区,id为奇数的发送到一个分区中,偶数的发送到另一个分区
//0 11381 2018/10/20 21:07 今天你还相信网恋吗:希望越大失望越大,技能省得莫名其妙,小规模团战打得又乱,最后一句,骄兵必败! 1 219517 3873092044 今天你还相信网恋吗 5 1540040820
String id=value.toString().split("\t")[0];
//将string -> int
int idint=Integer.parseInt(id);
//偶数的发送到另一个分区
if (idint%2==0){
return 0;
}else{
//id为奇数的发送到一个分区中
return 1;
}
}
@Override
public void close() {
}
@Override
public void configure(Map<String, ?> configs) {
}
}
/*查看打入数据分区数
cd /export/install/kafka_2.11-1.0.0/bin
./kafka-run-class.sh kafka.tools.GetOffsetShell --broker-list node01:9092,node02:9092,node03:9092 --topic 18BD12
*/
SparkStreaming消费Kafka数据写入MySql
package com.Job414.Job
import java.sql.{Connection, DriverManager, PreparedStatement}
import org.apache.kafka.clients.consumer.ConsumerRecord
import org.apache.kafka.common.serialization.StringDeserializer
import org.apache.spark.streaming.kafka010.{ConsumerStrategies, KafkaUtils, LocationStrategies}
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.streaming.dstream.{DStream, InputDStream, ReceiverInputDStream}
object KafkaToMysql {
def ToMysql(meaaageValue:String) ={
//meaaageValue====> 284 0 2018/10/20 21:08 文韜_:看得我....无言以对 0 0 1617054581 文韜_ 5 1540040880
println(meaaageValue)
val strings = meaaageValue.split("\t")
//数据写入mysql的动作
val connection: Connection = DriverManager.getConnection("jdbc:mysql://node02:3306/rng_comment?characterEncoding=UTF-8","root","123456")
var sql="insert into vip_rank (indexx,child_comment,comment_time,content,da_v,like_status,Pic,user_id,user_name,vip_rank,stamp) " +
"values (?,?,?,?,?,?,?,?,?,?,?);"
val ps: PreparedStatement = connection.prepareStatement(sql)
ps.setString(1,strings(0))
ps.setString(2,strings(1))
ps.setString(3,strings(2))
ps.setString(4,strings(3))
ps.setString(5,strings(4))
ps.setString(6,strings(5))
ps.setString(7,strings(6))
ps.setString(8,strings(7))
ps.setString(9,strings(8))
ps.setString(10,strings(9))
ps.setString(11,strings(10))
//执行插入
ps.executeUpdate()
}
def main(args: Array[String]): Unit = {
var kafkaParams= Map[String, Object](
"bootstrap.servers" -> "node01:9092,node02:9092,node03:9092",
"key.deserializer" -> classOf[StringDeserializer],
"value.deserializer" -> classOf[StringDeserializer],
"group.id" -> "SparkKafkaDemo",
"auto.offset.reset" -> "latest",
"enable.auto.commit" -> (false: java.lang.Boolean)
)
//1 创建SSC
var conf =new SparkConf().setMaster("local").setAppName("KafkaToMysql")
var sc =new SparkContext(conf)
sc.setLogLevel("WARN")
var ssc=new StreamingContext(sc,Seconds(5))
//2 到kafka读取所有数据
val kafkaDatas = KafkaUtils.createDirectStream[String, String](
ssc,
LocationStrategies.PreferConsistent,
ConsumerStrategies.Subscribe[String, String](Array("18BD12"), kafkaParams))
//3 过滤出星级为5的用户 使用\t切分数据,角标为9 的就是星级
val fiveDatas: DStream[ConsumerRecord[String, String]] = kafkaDatas.filter(a => {
if (a.value().split("\t")(9) == "5") {
true
} else {
false
}
})
//4 将星级为5的用户写入mysql
fiveDatas.foreachRDD(rdd=>{
//方法名:ToMysql foreach:遍历 meaasge.value :一条数据
rdd.foreach(meaasge=>ToMysql(meaasge.value()))
})
ssc.start()
ssc.awaitTermination()
}
}