Spark>SparkStreamingKafka 练习题

该博客介绍了如何使用SparkStreaming处理Kafka中的数据,包括数据预处理、从Kafka读取数据并写入MySQL的过程。在预处理阶段,排除了空行;接着将数据写入Kafka,依据特定字段进行分区;然后通过Spark Streaming从Kafka消费数据,最终将不同条件筛选后的数据存储到MySQL的各个表中,如微博会员等级为5的用户、评论赞数超过10的数据以及每天的评论数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

查看历史记录的命令
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()
  }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值