Spark core实战案例

本文介绍如何使用Spark进行点击流日志分析,包括统计PV、UV及TopN页面访问,以及将数据导入MySQL和Hbase的方法。通过具体代码示例,详细展示了数据处理流程。

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

1. 通过spark实现点击流日志分析案例

1.1 统计PV
  • 代码开发
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

//TODO:利用spark实现点击流日志分析---------> PV
object PV {
  def main(args: Array[String]): Unit = {
    //1、构建SparkConf
    val sparkConf: SparkConf = new SparkConf().setAppName("PV").setMaster("local[2]")

    //2、构建SparkContext   SparkContext该对象非常重要
      //它是所有spark程序的执行入口,它会构建DAGScheduler和TaskScheduler对象
    val sc = new SparkContext(sparkConf)
    sc.setLogLevel("warn")

    //3、读取数据文件
    val data: RDD[String] = sc.textFile("E:\\data\\access.log")

    //4、统计pv
    val pv: Long = data.count()
    println("PV:"+pv)


    sc.stop()

  }
}
1.2 统计UV
  • 代码开发
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.rdd.RDD

//TODO:利用spark实现点击流日志分析-----------UV
object UV {

  def main(args: Array[String]): Unit = {
    //1、构建SparkConf
    val sparkConf: SparkConf = new SparkConf().setAppName("UV").setMaster("local[2]")

    //2、构建SparkContext
    val sc = new SparkContext(sparkConf)
    sc.setLogLevel("warn")

    //3、读取数据文件
    val data: RDD[String] = sc.textFile("E:\\data\\access.log")


    //4、切分每一行,获取第一个元素 也就是ip
    val ips: RDD[String] = data.map( x =>x.split(" ")(0))

    //5、按照ip去重
    val distinctRDD: RDD[String] = ips.distinct()

    //6、统计uv
    val uv: Long = distinctRDD.count()
    println("UV:"+uv)


    sc.stop()

  }
}
1.3 统计TopN
  • 代码开发
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.rdd.RDD

//todo:利用spark实现点击流日志分析-----------TopN(求页面访问次数最多的前N位)
object TopN {
  def main(args: Array[String]): Unit = {
    //1、构建SparkConf
    val sparkConf: SparkConf = new SparkConf().setAppName("TopN").setMaster("local[2]")

    //2、构建SparkContext
    val sc = new SparkContext(sparkConf)
    sc.setLogLevel("warn")

    //3、读取数据文件
    val data: RDD[String] = sc.textFile("E:\\data\\access.log")

    //4、切分每一行,过滤出丢失的字段数据,获取页面地址
    val filterRDD: RDD[String] = data.filter(x=>x.split(" ").length>10)
    val urlAndOne: RDD[(String, Int)] = filterRDD.map(x=>x.split(" ")(10)).map((_,1))

    //5、相同url出现的1累加
    val result: RDD[(String, Int)] = urlAndOne.reduceByKey(_+_)

    //6、按照次数降序
    val sortedRDD: RDD[(String, Int)] = result.sortBy(_._2,false)


    //7、取出url出现次数最多的前5位
    val top5: Array[(String, Int)] = sortedRDD.take(5)
    top5.foreach(println)

    sc.stop()

  }

}

2. 通过spark读取文件数据写入mysql表中

  • 添加pom依赖
<dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <version>5.1.38</version>
</dependency>
2.1 foreach算子实现
  • 代码开发
import java.sql.{Connection, DriverManager, PreparedStatement}

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

object Data2MysqlForeach {
  def main(args: Array[String]): Unit = {
    //1、构建SparkConf
    val sparkConf: SparkConf = new SparkConf().setAppName("Data2MysqlForeach").setMaster("local[2]")

    //2、构建SparkContext
    val sc = new SparkContext(sparkConf)
    sc.setLogLevel("warn")

    //3、读取数据文件
    val data: RDD[String] = sc.textFile("E:\\data\\person.txt")

    //4、切分每一行    // id  name  age
    val personRDD: RDD[(String, String, Int)] = data.map(x => x.split(",")).map(x => (x(0), x(1), x(2).toInt))

    //5、把数据保存到mysql表中
        personRDD.foreach(line =>{
          //每条数据与mysql建立连接
          //把数据插入到mysql表操作
            //1、获取连接
              val connection: Connection = DriverManager.getConnection("jdbc:mysql://node03:3306/spark","root","123456")

            //2、定义插入数据的sql语句
              val sql="insert into person(id,name,age) values(?,?,?)"

            //3、获取PreParedStatement

             try {
               val ps: PreparedStatement = connection.prepareStatement(sql)

               //4、获取数据,给?号 赋值
               ps.setString(1, line._1)
               ps.setString(2, line._2)
               ps.setInt(3, line._3)
 				//执行
               ps.execute()
             } catch {
               case e:Exception => e.printStackTrace()
             } finally {
               if(connection !=null){
                 connection.close()
               }

             }
        })

    }
 }

2.2 foreachPartition 算子实现
  • 代码开发
import java.sql.{Connection, DriverManager, PreparedStatement}

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

object Data2MysqlForeachPartitions {
  def main(args: Array[String]): Unit = {
    //1、构建SparkConf
    val sparkConf: SparkConf = new SparkConf().setAppName("Data2MysqlForeachPartitions").setMaster("local[2]")

    //2、构建SparkContext
    val sc = new SparkContext(sparkConf)
    sc.setLogLevel("warn")

    //3、读取数据文件
    val data: RDD[String] = sc.textFile("E:\\data\\person.txt")

    //4、切分每一行    // id  name  age
    val personRDD: RDD[(String, String, Int)] = data.map(x => x.split(",")).map(x => (x(0), x(1), x(2).toInt))

    //5、把数据保存到mysql表中
    //使用foreachPartition每个分区建立一次链接,减少与mysql链接次数
    personRDD.foreachPartition( iter =>{
      //把数据插入到mysql表操作
      //1、获取连接
      val connection: Connection = DriverManager.getConnection("jdbc:mysql://node03:3306/spark","root","123456")

      //2、定义插入数据的sql语句
      val sql="insert into person(id,name,age) values(?,?,?)"

      //3、获取PreParedStatement

      try {
        val ps: PreparedStatement = connection.prepareStatement(sql)

        //4、获取数据,给?号 赋值
        iter.foreach(line =>{

          ps.setString(1, line._1)
          ps.setString(2, line._2)
          ps.setInt(3, line._3)
         //设置批量提交
          ps.addBatch()
        })
		//执行批量提交
        ps.executeBatch()
      } catch {
        case e:Exception => e.printStackTrace()
      } finally {
        if(connection !=null){
          connection.close()
        }

      }
    }

  }
}

3. 通过spark读取文件数据写入hbase表中

  • 添加pom依赖
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-client</artifactId>
            <version>1.2.1</version>
        </dependency>
  • 代码开发
import java.util

import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.hbase.{HBaseConfiguration, TableName}
import org.apache.hadoop.hbase.client.{Connection, ConnectionFactory, Put, Table}
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

//todo:通过spark读取数据文件,把结果数据保存到hbase表中
object Data2Hbase {

  def main(args: Array[String]): Unit = {
    //1、创建SparkConf
    val sparkConf: SparkConf = new SparkConf().setAppName("Data2Hbase").setMaster("local[2]")

    //2、构建SparkContext
    val sc = new SparkContext(sparkConf)
    sc.setLogLevel("warn")

    //3、读取文件数据
    val usersRDD: RDD[Array[String]] = sc.textFile("E:\\data\\users.dat").map(x=>x.split("::"))

    //4、保存结果数据到hbase表中
    usersRDD.foreachPartition(iter =>{

      //4.1 获取hbase的数据库连接
      val configuration: Configuration = HBaseConfiguration.create()
      //指定zk集群的地址
      configuration.set("hbase.zookeeper.quorum","node01:2181,node02:2181,node03:2181")
      val connection: Connection = ConnectionFactory.createConnection(configuration)

      //4.2 对于hbase表进行操作这里需要一个Table对象
      val table: Table = connection.getTable(TableName.valueOf("person"))

      //4.3 把数据保存在表中
      try {
        iter.foreach(x => {
          val put = new Put(x(0).getBytes)
          val puts = new util.ArrayList[Put]()
          //构建数据
          val put1: Put = put.addColumn("f1".getBytes, "gender".getBytes, x(1).getBytes)
          val put2: Put = put.addColumn("f1".getBytes, "age".getBytes, x(2).getBytes)
          val put3: Put = put.addColumn("f2".getBytes, "position".getBytes, x(3).getBytes)
          val put4: Put = put.addColumn("f2".getBytes, "code".getBytes, x(4).getBytes)

          puts.add(put1)
          puts.add(put2)
          puts.add(put3)
          puts.add(put4)

          //提交数据
          table.put(puts)
        })
      } catch {
        case e:Exception =>e.printStackTrace()
      } finally {
        if(connection !=null){
          connection.close()
        }
      }

    })

    sc.stop()
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值