spark的JDBC连接池(Scala版),及wordCount的结果保存到MySql中

一个Scala版的连接池,并在使用Spark Streaming进行Word Count时,把每批数据都存到mySql中

这里判断的两个空不能去掉,可能有人以为在调用getDriver方法时已经判断过pool.isEmpty了,在进行判断是没有意义的,而且当 连接数已经大于等于max时,会死循环,但是要考虑到运行过成中,在spark中是多线程运行的,在调用,getConnection方法时,可能当时pool中是空的,但是在调用后,可能其他线程的数据运行完了,会还连接, 那么此时再进行判断时pool就不是空了,两个调教都不成立,才能跳出循环,此时的情况是,获取的连接数已经大于等最大(max)的值,并且 已经有人把连接还了, 就可以直接取连接了,不用再创建,也不能再创建(连接数不能大于设置的最大连接数的)

import java.sql.{Connection, DriverManager}
import java.util

object JDBCConnectePools02 {
  private val max = 10  //设置连接最大数
  private val ConnectionNum = 10   //设置 每次可以获取几个Connection
  private var conNum =   0//连接数
  private val pool = new util.LinkedList[Connection]()  //连接池

  def getDriver() : Unit = {  //加载Driver
    //加载
    //这里判断的两个空不能去掉
    //可能有人以为在调用getDriver方法时已经判断过pool.isEmpty了,
    //在进行判断是没有意义的,而且当 连接数已经大于等于max时,会死循环
    //但是要考虑到运行过成中,在spark中是多线程运行的,在调用
    //getConnection方法时,可能当时pool中是空的,但是在调用后,
    //可能其他线程的数据运行完了,会还连接, 
    //那么此时再进行判断时pool就不是空了,两个调教都不成立,
    //才能跳出循环,此时的情况是,获取的连接数已经大于等最大(max)的值
    //并且 已经有人把连接换了, 就可以直接取连接了,不用再创建
    //,也不能再创建
    if(conNum < max && pool.isEmpty){ //
      Class.forName("com.mysql.jdbc.Driver")

    }else if(conNum>=max && pool.isEmpty){
      print("当前暂无可用Connection")
      Thread.sleep(2000)
      getDriver()
    }
  }
  def getConn(): Connection ={
    if(pool.isEmpty){
      getDriver()
      for(i <- 1 to ConnectionNum){  //创建10个连接
        val conn = DriverManager.getConnection("jdbc:mysql://hadoop01:3306/updatewordcount","root","root")
        pool.push(conn) //  把连接放到连接池中,push是LinkedList中的方法
        conNum += 1
      }
    }
    val conn: Connection = pool.pop()//从线程池所在LinkedList中弹出一个Connection,pop 是LinkedList的方法
    conn //返回一个Connection
  }

  def returnConn( conn :Connection): Unit ={ //还连接
    pool.push(conn)
  }

}

一个简单的使用,使用sparkStreaming,尽心wordCount,每次把结果放到MySql 中
这个代码里面一共有3foreach,分别是foreachRDD、froeachPartition
和foreach ,对于这三个foreach我的理解是,第一个foreachRDD是
DStream的方法,所以是不会触发job的,第二个foreachPartition
是rdd调用的,会触发job,
第三个foreach,是在foreachPartition中的,foreachPartition
中的函数的参数是指 每个分区中的数据对应的迭代器
所以这个foreach相当于Scala语言中的foreach,也不会提交job,可以用下面注释的for来代替

import java.sql.{Connection, PreparedStatement}

import org.apache.spark.SparkConf
import org.apache.spark.rdd.RDD
import org.apache.spark.streaming.dstream.{DStream, ReceiverInputDStream}
import org.apache.spark.streaming.{Duration, StreamingContext}

object JDBCWordCont02 {

  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("wc").setMaster("local[2]")
    //新建一个StreamingContext,每个5s是一个批次
    val ssc = new StreamingContext(conf,new Duration(5000))
   //接受hadoop01主机的 8888端口的数据
    val data: ReceiverInputDStream[String] = ssc.socketTextStream("hadoop01",8888)
    //进行切分压平
    val split: DStream[String] = data.flatMap(_.split(" "))
    //单词和1组合
    val wordAndOne: DStream[(String, Int)] = split.map((_,1))
    //对rdd进行遍历,想要使用foreachPartition 需要foreachRDD ,
    //对里面的rdd进行操作,DStream中没有foreachpartition方法,
    //如果直接使用foreach方法不好,会大量的去连接,还连接,对性能有影响
    wordAndOne.foreachRDD(rdd=>{
    //对RDD中的数据进行聚合
      val reduced: RDD[(String, Int)] = rdd.reduceByKey(_+_)
      reduced.foreachPartition(item =>{
      //获取连接
        val conn: Connection = JDBCConnectePools02.getConn()
     
		item.foreach(one=>{
		   val pstm: PreparedStatement = conn.prepareStatement("insert into  wordcount(word,count) values(?,?)")
          pstm.setString(1,one._1)
          pstm.setInt(2,one._2)
          pstm.executeUpdate()
		})
		/*上代码里面一共有3foreach,分别是foreachRDD、froeachPartition
		和foreach ,对于这三个foreach我的理解是,第一个foreachRDD是
		DStream的方法,所以是不会触发job的,第二个foreachPartition
		是rdd调用的,会触发job,
		第三个foreach,是在foreachPartition中的,foreachPartition
		中的函数的参数是指 每个分区中的数据对应的迭代器
		所以这个foreach相当于Scala语言中的foreach,也不会提交job,可以用下面注释的for来代替
		*/
		/*
        for(one <- item){ //把聚合后的数据存到mysql 中
          val pstm: PreparedStatement = conn.prepareStatement("insert into  wordcount(word,count) values(?,?)")
          pstm.setString(1,one._1)
          pstm.setInt(2,one._2)
          pstm.executeUpdate()
        }
        */
      //还连接
        JDBCConnectePools02.returnConn(conn)



      })
    })

    ssc.start()
    ssc.awaitTermination()
  }


}

你可能感兴趣的:(spark的JDBC连接池(Scala版),及wordCount的结果保存到MySql中)