Spark

Spark

spark安装与部署
(1)配置文件:conf/spark-env.shn
export JAVA_HOME=/usr/local/jdk1.8.0n
export SPARK_MASTER_HOST=spark01n
export SPARK_MASTER_PORT=7077
(2) 配置文件:conf/slaven spark02n spark03
(3) 启动Spark集群:start-all.sh

Spark HA 实现
参考:
export SPARK_DAEMON_JAVA_OPTS="-Dspark.deploy.recoveryMode=ZOOKEEPER -Dspark.deploy.zookeeper.url=spark01:2181,spark02:2181,spark03:2181 -Dspark.deploy.zookeeper.dir=/spark"
每个节点上,需要将以下两行注释掉
export SPARK_MASTER_HOST=spark01n
export SPARK_MASTER_PORT=7077
执行Spark Demo程序
1、执行Spark Example程序Demo:
蒙特卡罗求PI(求π)命令:spark-submit --master spark://spark01:7077 --class org.apache.spark.examples.SparkPi examples/jars/spark-examples_2.11-2.1.0.jar 100
2、使用Spark Shellspark-shell是Spark自带的交互式Shell程序,方便用户进行交互式编程,用户可以在该命令行下用scala编写spark程序。
(*)启动Spark Shell:spark-shell也可以使用以下参数:
参数说明:–master spark://spark10:7077
指定Master的地址–executor-memory 2g
指定每个worker
可用内存为2G–total-executor-cores 2
指定整个集群使用的cup核数为2个
例:spark-shell --master spark://spark01:7077 --executor-memory 2g --total-executor-cores 2
如果启动spark shell时没有指定master地址,但是也可以正常启动spark shell和执行spark shell中的程序,其实是启动了spark的local模式,该模式仅在本机启动一个进程,没有与集群建立联系。

什么是RDD
(1)RDD是整个spark 的计算基石,是分布式数据的抽象,为用户屏蔽了底层复杂的计算和映射环境
(2)RDD是不可变的,如果需要在一个RDD上进行转换操作,则会生成一个新的RDD
(3)RDD是分区的,RDD里面的具体数据是分布式存在多台机器的executor里面的,堆内内存+堆外内存+磁盘
(4)RDD是弹性的

1.存储 :Spark会根据用户的配置获得当前Spark的应用运行情况去自动将RDD的数据缓存到内存或者磁盘。他是一个对用户不可见的,封装起来的功能
2.容错:当你的RDD数据被删除或者丢失的时候,可以通过血统或者检查点机制恢复数据,这个用户透明的
3.计算:计算是分层的,有应用->Job->Stage->TaskSet->Task每一层都有对应的计算的保障与重复机制,保障你的计算不会因为突发因素而终止
4.分片:可以根据业务需求或者一些算子来重新调整RDD中的数据分布
2.SparkCore(操作RDD)
RDD的创建-》RDD的转换-》RDD的缓存-》RDD的行动-》RDD的输出
创建RDD的方式有三种
1.从scala集合中创建RDD sc.parallelize(seq) 把seq这个数据并行化分片到节点sc.makeRDD(seq) 把seq这个数据并行化分片到节点,他的实现就是parallelizesc.makeRDD(seq[T,seq]) 这种方式可以指定seq的存放位置
2.从外部存储创建RDD比如 sc.textFile(“path”)
3.从其他RDD转换

transformations(转换) action(行动)的区别转换:
通过操作将一个RDD转换成另一个RDD(懒执行)行动:
将一个RDD进行求值或输出所有这些操作主要针对两种类型的RDD
(1)数值RDD
(2)键值对RDD
只有action的时候RDD才会真的去执行(优化)

算子
这里只列举了一些

object TestDemo {  
def main(args: Array[String]): Unit = {  
          val conf=new SparkConf().setAppName(this.getClass.getSimpleName).setMaster("local[*]")   
          val sc = new SparkContext(conf)    
          //transformation
          //combineByKey    
          val array=Array(("java",98),("php",89),("hadoop",89),("java",88),("php",85),("hadoop",82))    
          val input: RDD[(String, Int)] = sc.parallelize(array)    
          val comp=input.combineByKey(     
           (v)=>(v,1),      
           (acc:(Int,Int),v)=>(acc._1+v,acc._2+1),     
            (acc1:(Int,Int),acc2:(Int,Int))=>(acc1._1+acc2._1,acc1._2+acc2._2)    )
            //    comp.foreach(println(_))
            //aggregateByKey   简化操作foldByKey    
            var rdd=sc.makeRDD(List((1,2),(1,3),(2,3),(3,8),(4,9),(3,5)),3)    
            rdd.aggregateByKey(0)(math.max(_,_),_+_)    
            rdd.foldByKey(0)(_+_)
            //cogroup  在類型為(K,V)和(K,W)的RDD上調用,返回一個(K,(Iterable(v)),(Iterable(w)))類型的RDD    
            //笛卡爾積   
             var a=sc.makeRDD(1 to 3)    
             var b=sc.makeRDD(4 to 6)    
             a.cartesian(b)
               //pipe 管道操作 類似mappartition (对于每个分区,都执行一个perl或shell脚本,返回输出的RDD),   
               //coalesce 缩减分区数,用于大数据集过滤后,提高小数据集的执行效率   
               //repartition 根据分区数重新通过网络分区所有数据(重型操作)  
               //glom 将每一个分区形成一个数组      
               //subtract 去除两个RDD 中相同的
               //action   
               //reduce collect count first take takeSample(返回一个数组)  takeOrdered(返回前几个的排序) fold    
               //saveAsTextFile 文本方式    
               val rdd2=sc.makeRDD(1 to 10,2)    
               rdd2.aggregate(1)(      
               {(x:Int,y:Int) =>x+y},  
               //得到第一个分区相加值     
                {(a:Int,b:Int)=> a+b}     
                //通过第一个分区相加值再去相加得到最终值   
                 )
                //当在RDD 中使用到了class的方法或者属性 ,该class需要继承java.io.Serializable接口,或者可以将属性赋值为本地变量来防止整个对象的传输 
                 }
                 

RDD依赖关系
1.RDD依赖关系分为宽依赖和窄依赖
2.窄依赖是说父RDD的每一个分区最多被一个子RDD的分区应用,也就是说它的出度为1
3.宽依赖是说父RDD的每一个分区被多个子RDD的分区应用,也就是说它的出度大于等于2
4.应用在整个过程中,RDD形成的产生关系,就叫做血统关系,RDD在没有持久化时默认是不保存的,如果需要,那么就要根据血统关系来重新计算
5.应用在执行过程中,是分为多个Stage来进行的,划分stage的关键,就是判断是不是存在宽依赖,从action往前去推整个Stage 的划分
RDD的持久化
1.RDD的持久化主要通过persist和cache操作来实现,cache操作就相当于StoageLevel为MEMORY_ONLY的persist操作
2.持久化它的存储等级可以分为:存储位置(磁盘,内存,非堆内存),是否序列化,存储的份数(1,2)
checkpoint用于hdfs(不存在血统关系) cache 用于内存上(存在血统关系)先cache 再checkpoint
RDD CheckPoint
1.创建一个RDD val check=sc.makeRDD(1 to 10)
2.设置SparkContext的checkpoint目录,如果你要用spark-shell,那么就是 sc.setCheckPointDir(“hdfs://hadoop01:9000/check”)
3.在RDD 上调用checkpoint方法 check.checkpoint
4.触发RDD的行动操作,让RDD的数据真实写入checkpoint目录
注意:整个checkpoint读取时用户透明

RDD DataSet DataFrame 之间的转换
RDD—>DataFrame :rdd.map(para=>(para(0).trim,para(1).trim.toInt)).toDF(“name”,“age”)
DataFrame—>RDD :dataframe.rdd

RDD—>DataSet :rdd.map(para=>Person(para(0).trim,para(1).trim.toInt)).toDS
DataSet—>RDD :DataSet.rdd

DataFrame—>DataSet :dataframe.to[Person]DataSet—>DataFrame :dataset.toDF

下面奉上从redis 以及mysql 传值与取值代码

1.redis

package day08

import org.apache.commons.pool2.impl.GenericObjectPoolConfig
import redis.clients.jedis.{Jedis, JedisPool}

object Jpools {
private val config = new GenericObjectPoolConfig()
  private val pool = new JedisPool("192.168.198.110",6379)
  def getJedis:Jedis={
    val resource = pool.getResource
    resource.select(1)
    resource
  }

}

package day08

import day04.MyUntil
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.broadcast.Broadcast
import org.apache.spark.rdd.RDD

object CoreToRedis {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName(this.getClass.getSimpleName).setMaster("local[*]")
    val sc = new SparkContext(conf)

    //获取起始位置
    val index: RDD[(Long, Long, String)] =sc.textFile("D:\\test\\ip.txt").map(tp=>{
      val split=tp.split("[|]")
      val start=split(2).toLong
      val end=split(3).toLong
      val provice=split(6)
      (start,end,provice)
    })
    //array
    val array: Array[(Long, Long, String)] = index.collect()
    val arrays: Broadcast[Array[(Long, Long, String)]] = sc.broadcast(array)
    //获取access 的ip地址
    val ip: RDD[(String, Int)] = sc.textFile("D:/test/access.log").map(tp=>{
      val split=tp.split("[|]")
      val ip=split(1)

      val ips=MyUntil.ip2Long(ip.toString())

      val array2: Array[(Long, Long, String)] =arrays.value
      val i: Int = MyUntil.find(array2,ips)

      var pro=""
      if(i != -1){
        val value: (Long, Long, String) = array2(i)
        pro=value._3
      }
      (pro,1)
    })
    val value: RDD[(String, Int)] = ip.reduceByKey(_+_)
    //读出来
    value.mapPartitions(filter=>{
      val jedis = Jpools.getJedis

     val aa: Iterator[String] =filter.map(tp=>{
        val str = jedis.hget("aa","云南")
       str
      })
    jedis.close()
      aa


    }).foreach(println(_))

//写进去
//    value.foreachPartition(filter=>{
//      val jedis = Jpools.getJedis
//      filter.foreach(tp=>{
//        jedis.hincrBy("aa",tp._1,tp._2)
//      })
//      jedis.close()
//    })
  }
}

2.mysql

package day08

import java.util.Properties

import day07.DataFrameToRedis.ip2Long
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.types.{LongType, StringType, StructField}
import org.apache.spark.sql.{Row, SaveMode, SparkSession, types}

object DataFrameToRedis {
  def main(args: Array[String]): Unit = {
    val session = SparkSession.builder().appName(this.getClass.getSimpleName).master("local[*]").getOrCreate()

    import  session.implicits._
    val result1: RDD[Row] = session.sparkContext.textFile("D:\\test\\ip.txt").map(tp=>{
      val split = tp.split("[|]")
      Row(split(2).toLong,split(3).toLong,split(6))
    })

    val result2: RDD[Row] =session.sparkContext.textFile("D:\\test\\access.log").map(tp=>{
      val split = tp.split("[|]")
      Row(ip2Long(split(1)))
    })

    val schemaip=types.StructType{
      List(
        StructField("ip",LongType)
      )
    }
    val schemaipresults=types.StructType{
      List(
        StructField("ipstart",LongType),
        StructField("ipend",LongType),
        StructField("provice",StringType)
      )
    }

    val ipNum=session.createDataFrame(result2,schemaip)
    val ipres=session.createDataFrame(result1,schemaipresults)
    ipres.createTempView("result1")
    ipNum.createTempView("iptable")
    val result3 = session.sql(
      """
        |select  result1.provice,count(1) counts
        |from result1
        |join iptable
        |on iptable.ip >=result1.ipstart and iptable.ip <= result1.ipend
        |group by result1.provice order by counts
        |desc limit 10
      """.stripMargin)
   val properties = new Properties()
//    properties.setProperty("user","root")
//    properties.setProperty("password","root")
//    result3.write.mode(SaveMode.Append).jdbc("jdbc:mysql://localhost:3306/test1","ip",properties)
    properties.setProperty("user","root")
      properties.setProperty("password","root")
    session.read.jdbc("jdbc:mysql://localhost:3306/test1","ip",properties).foreach(println(_))


  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值