spark入门笔记scala版

基本使用

打开python版本的spark shell方式:bin/pyspark
打开scala版本的spark shell方式:bin/spark-shell
conf/log4j.properties
log4j.rootCategory=INFO,console 改为WARN,console,降低日志级别,减少无用日志输出

lines=sc.textFile("a.txt")
lines.count()
lines.first()

RDD(Resilient Distributed Dataset)

每个RDD都被分为多个分区,这些分区运行在集群中的不同节点上。
可使用个两种方法创建RDD:读取一个外部数据集,或在驱动器程序里分发驱动器程序中的对象集合。
RDD支持两种类型的操作:transformation和action。transformation由一个RDD生成一个新的RDD。action对RDD计算出一结果,把结果返回到驱动器程序里。
默认情况下,Spark的RDD会在进行action操作时重新计算。如果想在多个action中重用同一个RDD,可使用RDD.persist()让spark把这个RDD缓存下来,RDD.unpersist()删除cache。

spark程序的工作步骤:

1)从外部数据创建出输入RDD
2)使用诸如filter()这样的转化操作对RDD进行转化,以定义新的RDD
3)告诉spark对需要被重用的中间结果RDD执行persist()操作
4)使用action操作来触发一次并行计算,spark会对计算进行优化后再执行。

创建RDD

  1. 直接从集合转化
lines=sc.parallelize(["hello","world"])
sc.parallelize(List(1,2,3,4,5,6,7,8,9,10))
  1. 从分布式文件系统来
sc.textFile(“README.md”)
sc.textFile(“hdfs://xxx”)
  1. 从任何Hadoop InputFormat来
sc.hadoopFile(keyClass, valClass, inputFormat,conf)

简单例子

val lines = spark.textFile("hdfs://....")
val errors = lines.filter(_.startswith("ERROR"))
val messages = errors.map(_.split('\t')(2))
messages.cache()
messages.filter(_.contains("foo")).count
messages.filter(_.contains("bar")).count

简化后

val message=spark.textFile("hdfs://...").filter(_.startsWith("ERROR")).map(_.split('\t')(2)).cache
def getStatistic(keyword): Long = message.filter(_contains(keyword)).count
  • transformation操作(延迟执行)
filter()操作不会改变已有的inputRDD中的数据,而是会返回一个全新的RDD
map()接收一个函数,把这个函数用于RDD中的每个元素,将函数的返回结果作为结果RDD中对应元素的值。map()的返回值类型不需要和输入类型一样。
flatMap()对每个输入元素生成多个输出元素。提供给flatMap()的函数分别应用到了输入RDD的每个元素上,返回的不是一个元素,而是一个返回值序列的迭代器。输出的RDD不是由迭代器组成的,得到的是一个包含各个迭代器可访问的所有元素的RDD。及flatMap()将返回的迭代器”拍扁”
union()
intersection()
subtract()
cartesian()

RDD、 mappedRDD、 flatMappedRDD比较:

RDD1{"coffee panda","happy panda","happies panda party"}
mappedRDD{["coffee","panda"],["happy","panda"],["happies","panda","party"]}
flatMappedRDD{["coffee","panda","happy","panda","happies","panda","party"]}

action操作

count()
take(num) 从RDD中返回num个元素
collect()获取整个RDD中的数据,只有当整个数据集能在单台机器内存中时,才可以使用collect().大部分情况下使用saveAsTextFile() saveAsSequenceFile()把RDD的数据内容以自带的格式保存起来
reduce()接收一个函数作为参数,操作两个相同元素类型的RDD数据并返回一个同样类型的新元素。主要做聚合操作。要求返回值和输入类型一样。
aggregate()通过一个函数把RDD中的元素合并起来放入累加器,返回值类型不需要和输入类型一样
top(num)从RDD中返回最前面的num个元素

PairRDD

创建pairRDD

pairs=lines.map(lambda x:(x.split(" ")[0],x))

所有RDD中的传递函数规则同样适用于pairRDD,由于pairRDD中包含二元组,所以需要传递的函数应当操作二元组而不是独立的元素
以键值对集合{(1,2),(3,4),(3,6)}为例

\
操作描述结果
reduceByKey(func) 合并具有相同key的值rdd.reduceByKey((x,y)=>x+y) {(1,2),(3,10)}
groupByKey() 对具有相同key的值进行分组rdd.groupByKey() {(1,[2]),(3,[4,6])}
mapValues()rdd.mapValues(x=>x+1){(1,3),(3,5),(3,7)}
flatMapValues()rdd.flatMapValues(x=>(x to 5)) {(1,2),(1,3),(1,4),(1,5),(3,4),(3,5)}
keys() {1,3,3}
values(){2,4,6}
sortByKey() {(1,2),(3,4),(3,6)}
combineByKey()
rightOuterJoin()
leftOuterJoin()
cogroup()

注意怎样控制reduce task的数量

xx.reduceByKey(_+_,10) #10个reduce task
xx.groupByKey(5) # 5个reduce task

累加器和广播变量 (两种不同的共享变量)

累加器(accumulator)用来对信息进行聚合,只有写的操作(这使得累加器的实现可以更加高效,不需要对每次更新操作进行复杂的通信),提供了将工作节点中的值聚合到驱动程序中的语法。

blankLines=sc.accumulator(0)

广播变量(broadcast variable)用来高效分发较大的对象

signPrefixed=sc.broadcast(localCallSignTable())

Spark Streaming

Dstream随时间推移而收到的数据的序列,每个时间区间收到的数据都作为RDD存在,DStream由这些RDD所组成的序列,Dstream可以从各种输入源创建(flume/kafka/HDFS),支持两种操作,transformation和output operation。没有action操作。
StreamingContext

转化操作分为无状态和有状态
无状态(stateless):每个批次的处理不依赖与之前批次的数据,如map() filter() reduceByKey()

有状态(stateful):需要使用之前批次的数据或者是中间计算结果来计算当前批次的数据。

MR/DataFlow
spark
.textFile("hdfs://...")
.flatMap(_ split " ")
.map(_ -> 1)
.reduceByKey(_ + _)
.collectAsMap()
Streaming
val streaming = new StreamingContext(
spark, Seconds(1))
streaming.socketTextStream(host, port)
.flatMap(_ split " ")
.map(_ -> 1)
.reduceByKey(_ + _)
.print()
streaming.start()
SQL
val hiveContext = new HiveContext(spark)
import hiveContext._
val children = hiveql(
"""SELECT name, age FROM people
|WHERE age < 13
""".striMargin).map {
case Row(name: String, age: Int) =>
name -> age
}.foreach(println)
Machine Learning
val points = spark.textFile("hdfs://...")
.map(_.split.map(_.toDouble)).splitAt(1)
.map { case (Array(label), features) =>
LabeledPoint(label, features)
}
val model = KMeans.train(points)
MapReduce & SQL
// ETL with Spark Core
case class Person(name: String, age: Int)
val people = spark.textFile("hdfs://people.txt").map { line =>
val Array(name, age) = line.split(",")
Person(name, age.trim.toInt)
}.registerAsTable("people")
// Query with Spark SQL
val teenagers = sql("SELECT name FROM people WHERE age >= 13 AND age <= 19")
teenagers.collect().foreach(println)
SQL & iterative computation (machine learning)
// ETL with Spark SQL & Spark Core
val trainingData = sql("""SELECT e.action, u.age, u.latitude, u.longitude
|FROM Users u JOIN Events e ON u.userId = e.userId
""".stripMargin).map {
case Row(_, age: Double, latitude: Double, longitude: Double) =>
val features = Array(age, latitude, longitude)
LabeledPoint(age, features)
}
// Training with MLlib
val model = new LogisticRegressionWithSGD().run(trainingData)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值