spark的任务提交流程
shuffle过程分析
rdd的特点与五大属性
1、SparkStreaming + Kafka ----Receiver
用的是Kafka高层次的消费者api,不能自己维护offset
object Sparkkafka08ReceiverDStream {
def main(args: Array[String]): Unit = {
val sparkContext = new SparkContext(new SparkConf()
.setMaster("local[6]")
.setAppName("08ReceiverDstream")
.set("spark.streaming.receiver.writeAheadLog.enable","true")) //开启WAL预写日志,保存数据源端安全性
sparkContext.setLogLevel("WARN")
val streamingContext = new StreamingContext(sparkContext,Seconds(5))
//zk地址
val zkQuorum = "node-1:2181,node-2:2181,node-3:2181"
//消费组
val groupId = "sparkkafka_group"
//topic相关信息Map[String,Int],topic名称->分区数
val topics = Map("kafkatopic"->3)
//开启3个Receiver接收数据,每一个receiver都是一个独立的线程,去接收一个分区里面的数据
val eachPatitionStream: immutable.IndexedSeq[ReceiverInputDStream[(String, String)]] = (1 to 3).map(x => {
//使用receiverDstream的方式进行消费,消费模式使用的是kafka的HighLevelAPI,offset都保存在zk中
val stream: ReceiverInputDStream[(String, String)] = KafkaUtils.createStream(streamingContext, zkQuorum, groupId, topics) //只是相当于开启了一个receiver
stream
})
//合并三个分区里面的数据
//DStream里面保存的是一个元组,第一个数据是卡夫卡当中每条数据key,第二个数据是kafka当中每条数据value
val result: DStream[(String, String)] = streamingContext.union(eachPatitionStream)
result.print()
streamingContext.start()
streamingContext.awaitTermination()
}
}
2、SparkStreaming + Kafka ----Direct
Direct模式使用kafka的低阶API进行消费,这种API可以对offset进行操作,Receiver采用zookeeper管理offset,而Direct模式采用Spark自己管理,将offset存贮在topic中。
Direct模式相对于Receiver模式简化了并行度,Direct模式读取topic数据对应的并行度与topic的partition个数相同。也即是rdd的分区数?
kafka0.11之后彻底抛弃了reciver模式,可以手动提交offset,进行offset的管理维护,保证数据不会丢失,推荐使用。
/**
* 使用lowLevelAPI进行消费,数据的offset都保存到topic里面去了
* 这种整合方式不需要手动的开启多个receiver线程去消费数据
*/
object sparkkafka08DirectDStream {
def main(args: Array[String]): Unit = {
val sparkContext = new SparkContext(new SparkConf().setAppName("08DirectDStream").setMaster("local[6]"))
sparkContext.setLogLevel("WARN")
val streamingContext = new StreamingContext(sparkContext,Seconds(5))
//配置kafka相关参数
val kafkaParams = Map("metadata.broker.list"->"node-1:9092,node-2:9092,node-3:9092","group.id"->"Kafka_Direct")
//要消费的topic名字
val topics = Set("kafkatopic")
val result: InputDStream[(String, String)] = KafkaUtils.createDirectStream[String,String,StringDecoder,StringDecoder](streamingContext,kafkaParams,topics)
val topicDatas: DStream[String] = result.map(x=>x._2)
//topicDatas.print()
val wordNum: DStream[(String, Int)] = topicDatas.flatMap(x=>x.split(" ")).map((_,1)).reduceByKey(_+_)
wordNum.print()
streamingContext.start()
streamingContext.awaitTermination()
}
}
/**
* 通过0.10版本用DirectDStream的方式实现数据的消费
*/
object kafka010DirectDStream {
def main(args: Array[String]): Unit = {
val sparkContext = new SparkContext(new SparkConf().setMaster("local[6]").setAppName("010DirectDStream"))
sparkContext.setLogLevel("WARN")
val streamingContext = new StreamingContext(sparkContext,Seconds(5))
val locationStrategy: LocationStrategy = LocationStrategies.PreferConsistent
val topics = Array("kafkatopic")
val brokers= "node-1:9092,node-2:9092,node-3:9092"
val sourcetopic="kafkatopic"
//创建消费者组
var group="sparkafkaGroup"
//消费者配置
val kafkaParam = Map(
"bootstrap.servers" -> brokers,//用于初始化链接到集群的地址
"key.deserializer" -> classOf[StringDeserializer],
"value.deserializer" -> classOf[StringDeserializer],
//用于标识这个消费者属于哪个消费团体
"group.id" -> group,
//如果没有初始化偏移量或者当前的偏移量不存在任何服务器上,可以使用这个配置属性
//可以使用这个配置,latest自动重置偏移量为最新的偏移量
"auto.offset.reset" -> "latest",
//如果是true,则这个消费者的偏移量会在后台自动提交
"enable.auto.commit" -> (false: java.lang.Boolean)
);
val consumerStrategy: ConsumerStrategy[String, String] = ConsumerStrategies.Subscribe(topics,kafkaParam)
val result: InputDStream[ConsumerRecord[String, String]] = KafkaUtils.createDirectStream[String,String](streamingContext,locationStrategy,consumerStrategy)
//循环遍历每一个RDD当中的数据
result.foreachRDD(iter => {
if(iter.count() > 0){