potatoknight

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
val lines = sc.textFile("data.txt")
val lineLengths = lines.map(s => s.length)
val totalLength = lineLengths.reduce((a, b) => a + b)
spark是懒惰运行的,上面两行都不会直接执行,直到要开始执行reduce 这个action的时候才会执行

明白闭包 closure
以一个例子作为说明
val counter = 0
val rdd = sc.parallelize(data)

rdd.foreach(x => counter += x)
println("counter value= " + counter)
rdd.foreach(x => println(x))

在计算rdd.foreach的时候,rdd被split到了不同的计算节点上,在此之前spark会计算出来闭包,然后将闭包传递给每个Node进行计算。这个闭包当中就包含了全局变量counter的副本,那么在集群上修改的仅仅是副本,最终driver中的counter是不会被改变的。如果在单机上运行,也取决于是否运行于同一个JVM当中,如果在一个JVM当中,则可能侥幸会更新全局counter。这种想在闭包内操作闭包外变量的行为在spark里是未定义的。对于这种情况,可以使用Accumulator

所以,不要在rdd的操作中修改全局变量

 另一个 rdd.foreach(x => println(x)) 也是不行的,在分布式情况下,stdout是各个executor的stdout,driver是不会输出任何东西的,可以用rdd.collect.foreach(x => println(x)),但这有一个严重的问题,可能OOM,如果只是看其中一部分,可以使用rdd.take(100).foreach(x => println(x))  

 

定义函数

//完整的函数定义
def f1(i:Int) : String = {
    "value=" + i
}
// 省略返回值和等号
def f2(i:Int){
  println(i)
}
// 省略了参数和返回值定义
def f3 ={
  "111"
}
// f4等于一个匿名函数
def f4 = () =>{
  "fsfsf"
}

 

 

Functions & Evaluations

1、如果CBV 能终止,那么CBN也能终止。

2、反之不然

def first(x: Int, y: Int) = x

first(1, loop)  CBV = 1
first(1, loop)  CBN = 无限循环

 

 

The difference between val and def becomes apparent when the right hand side does not terminate. Given

def loop: Boolean = loop
def x = loop // 只是给loop 起了另外一个名字,OK
val x = loop // BAD,val会在复制的那一刻计算表达式

 

测试scala程序

写完一个scala之后,sbt,进入sbt命令行模式

> pachage //打包
> run //运行程序 从main函数开始运行,或者object 继承(extends)了App,这样就不用定义main函数

或者在sbt console里面

sbt console
scala > import example.session._
scala > sqrt_self(4)

 

函数

Int => Int // 就是一个参数类型为Int 返回值也为 Int的匿名函数

def sum(f: Int => Int, a: Int, b: Int): Int = {
   def loop(a: Int, acc: Int):Int = {
      if (a > b) acc
      else loop(a+1, f(a) + acc)
   }
   loop(a, 0)
} // a到b的 f 和,tail recursion 

sum(x => x * x, 3, 5)

 

 

数据的共享内存处理和分布式处理的区别

共享内存处理:是一份数据会被在内存中切成若干块,然后被若干个thread处理,最后合并起来

分布式处理:是将一份数据分成若干块,放在不同的机器上面(机器取代了共享内存),每个机器可以成为一个Node(Node取代了thread),每台机器单独处理,最后合并起来

由此引发的一个问题:分布式处理需要考虑网络延迟 network latency,因为节点之间存在着数据交换和通信,这会影响到程序设计

 

分布式系统需要处理的两个问题:

容错

网络延迟

 创建RDD

1、可以从已有的RDD创建

2、从SparkContext 创建

    parallelize:convert a local scala collection to RDD

    textFIle:read a text file from HDFS or lcoal file system and return a RDD

 

重命名  rename hdfs 文件

https://bigdata-etl.com/apache-spark-how-to-rename-or-delete-a-file-from-hdfs/

package com.bigdataetl
import org.apache.hadoop.fs.{FileSystem, Path}
import org.apache.spark.sql.SparkSession
object Test extends App {
  val spark = SparkSession.builder
    // I set master to local[*], because I run it on my local computer.
    // I production mode master will be set rom s
    .master("local[*]")
    .appName("BigDataETL")
    .getOrCreate()
  // Create FileSystem object from Hadoop Configuration
  val fs = FileSystem.get(spark.sparkContext.hadoopConfiguration)
  // Base path where Spark will produce output file
  val basePath = "/bigtadata_etl/spark/output"
  val newFileName = "renamed_spark_output"
  // Change file name from Spark generic to new one
  fs.rename(new Path(s"$basePath/part-00000"), new Path(s"$basePath/$newFileName"))

 

判断hdfs 文件是否存在

val conf = sc.hadoopConfiguration
val fs = org.apache.hadoop.fs.FileSystem.get(conf)
val exists = fs.exists(new org.apache.hadoop.fs.Path("/path/on/hdfs/to/SUCCESS.txt"))

 

remove 删除 hdfs 文件

https://bigdata-etl.com/apache-spark-how-to-rename-or-delete-a-file-from-hdfs/

package com.bigdataetl
import org.apache.hadoop.fs.{FileSystem, Path}
import org.apache.spark.sql.SparkSession
import scala.sys.process._
object SparkDeleteFile {
  val spark = SparkSession.builder
    // I set master to local[*], because I run it on my local computer.
    // I production mode master will be set rom s
    .master("local[*]")
    .appName("BigDataETL")
    .getOrCreate()
  // Create FileSystem object from Hadoop Configuration
  val fs = FileSystem.get(spark.sparkContext.hadoopConfiguration)
  // Delete directories recursively using FileSystem class
  fs.delete(new Path("/bigdata_etl/data"), true)
  // Delete using Scala DSL
  s"hdfs dfs -rm -r /bigdata_etl/data/" !
  // Delete file
  fs.removeAcl(new Path("/bigdata_etl/data/file_to_delete.dat"))
  // Delete using Scala DSL
  s"hdfs dfs -rm /bigdata_etl/data/file_to_delete.dat" !

 

重命名本地文件 local file

import java.io.File
import util.Try

def mv(oldName: String, newName: String) = 
  Try(new File(oldName).renameTo(new File(newName))).getOrElse(false)

 

判断本地文件是否存在 local file

scala> import java.nio.file.{Paths, Files}
import java.nio.file.{Paths, Files}

scala> Files.exists(Paths.get("/tmp"))
res0: Boolean = true

 

intellij idea 远程调试 spark 程序

先执行

export SPARK_SUBMIT_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=4000

然后设置idea

Rub-> Edit Configuration -> Click on "+" left top cornor -> Remote -> set port and name

然后 

spark-submit --class com.your.Appp --master local target/scala-2.11/your-app-assembly-1.0.jar

这个时候会出现

Listening for transport dt_socket at address: 4000

然后回到idea,下断点,点击 debug 开始调试

http://www.bigendiandata.com/2016-08-26-How-to-debug-remote-spark-jobs-with-IntelliJ/

 

local模式web ui 监控

http://10.20.202.222:4041/

 

 

idea debug 调试executor

1、提交的时候用下面的配置

--num-executors 1 
--executor-cores 1
--conf spark.executor.extraJavaOptions=-agentlib:jdwp=transport=dt_socket,server=n,address=xxx.xxx.xxx.xxx:4000,suspend=n \

2、在idea里面设置 Run - Edit Configuration ,如果没有Remote就点击➕新建一个,然后将Host设置为自己电脑的IP,debug mode 设置成listen to remote JVM

https://stackoverflow.com/questions/29090745/debugging-spark-applications

 

spark操作多个集群

https://www.jianshu.com/p/3e84c4c97610

posted on 2018-10-29 10:20  potatoknight  阅读(286)  评论(0编辑  收藏  举报