Spark Streamng实战

Spark Streamng 是一个可拓展,大规模,高吞吐量,高容错性的实时流处理数据程序
    将不同数据源的数据经过SparkStreaming处理之后结果输出到外部文件系统

特点
    低延时
    能从错误中高效的恢复: fault-tolerant
    能够运行在成百上千的节点
    能够将批处理、机器学习,图计算的子框架和SparkStreaming综合起来使用

流程:
    1、将接受的数据拆分成批次数据,然后被spark engine处理得出结果,返回也是以批次返回


Spark Executor
Executor是spark任务(task)的执行单元,运行在worker上,但是不等同于worker,实际上它是一组计算资源(cpu核心、memory)的集合。
一个worker上的memory、cpu由多个executor共同分摊。         

spark-submit 的使用
使用spark-submit来提交我们的spark应用程序运行的脚本
./spark-submit --master local[2] \
--class org.apache.spark.examples.streaming.NetworkWordCount \
--name NetworkWordCount \
/opt/spark/lib/spark-examples-1.6.0-hadoop2.2.0.jar

spark-shell 来提交程序(测试)
import org.apache.spark.streaming.{Seconds, StreamingContext}
val ssc = new StreamingContext(sc, Seconds(3))
val lines = ssc.socketTextStream("testhdp01", 9999)
val words = lines.flatMap(_.split(" "))
val wordCounts = words.map(x => (x, 1)).reduceByKey(_ + _)
wordCounts.print()
ssc.start()
ssc.awaitTermination()


SparkStreaming 核心概念
1、StreamingContext  文件入口,SparkStreaming程序的生命周期

Spark源码:

  def this(conf: SparkConf, batchDuration: Duration) = {
    this(StreamingContext.createNewSparkContext(conf), null, batchDuration)
  }

一个StreamingContext能被创建是基于一个SparkConf对象


创建StreamingContext步骤:
var conf = new SparkConf().setAppName(appName).setMaster(master)
val ssc = new StreamingContext(conf,seconds(1))//批次的间隔,1代表1秒执行一次SparkStream的切分数据

After a context is defined, you have to do the following.
    
  1.  Define the input sources by creating input DStreams. //定义输入的数据流
  2.  Define the streaming computations by applying transformation and output operations to DStreams.//可对输入的数据源进行转换和输出
  3.  Start receiving data and processing it using streamingContext.start().//接受和处理数据的命令
  4.  Wait for the processing to be stopped (manually or due to any error) using streamingContext.awaitTermination().
  5.  The processing can be manually stopped using streamingContext.stop().

2、DStream :discretied stream
持续化的数据流
象征的是一系列的RDD

对DStream操作算子,比如map/flatMap,其实底层会被翻译为对DStream中的每个RDD都有做相同的操作,
因为一个DStream是由不同批次的RDD所构成的

3、Input DStream and Receivers
Input DStreams are DStreams representing the stream of input data received from streaming sources.
输入流代表从数据源接收过来的数据流
Every input DStream (except file stream, discussed later in this section) is associated
with a Receiver (Scala doc, Java doc) object which receives the data from a source and stores
it in Spark’s memory for processing.
每一个输入流(除了数据源是文件系统外)都需要关联一个Receivers用于接收数据,并在spark内存中处理接收的数据

运行sparkstream master 模式时,不能用local或者local[1],一个线程只能接收处理一个数据流,所以local[n]的n必须大于receivers的数据量


4、Transformation and Output Operations
Transformation:类似RDD,利用函数方法修改处理接受的数据流
Output Operations:输出保存处理后的数据流


UpdateStateByKey 带状态的算子
一个自定义方法,可以计算统计正在持续更新的文件
需先设置checkpoint目录:ssc.checkpoint
定义好作用于DStream:  val state = wordcount.updateStateByKey[Int](updateFunction _)
  /**
    * 更新已有与新增的数据
    * @param currentValues
    * @param previousCount
    * @return
    */
  def updateFunction(currentValues: Seq[Int], previousCount: Option[Int]): Option[Int] = {
    val newCount = currentValues.sum  // add the new values with the previous running count to get the new count
    val preCount = previousCount.getOrElse(0)
    Some(newCount+preCount)
    
  }
 
需求:将统计结果写入到mysql数据库中
create table wordcount(
word varchar(50) default  null,
wordercount int(10)
);

def main (args: Array[String]): Unit ={
    System.setProperty("hadoop.home.dir","D:\\hadoop-common-2.2.0-bin-master")
    //设置StreamContext
    val conf = new SparkConf().setAppName("xxx").setMaster("local[*]")
    val ssc = new StreamingContext(conf,Seconds(5))
    
    //监听socket端口数据,test01hdp机子上得6789端口, 端口命令 nc -lk 6789
    val line = ssc.socketTextStream("test01hdp",6789)
    //统计数据
    val result = line.flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_)
    //foreach结果写入数据库
    result.foreachRDD(rdd=>{
        //先将结果分区
        rdd.foreachPartition(partitionOfRecords=>{
            //获取数据库连接
            val conn = getConnection()
            //遍历分区中的每条记录
            partitionOfRecords(record=>{
                //创建sql语句将记录插入数据库
                val sql = "insert into wordcount values ('"+ record._1 + "',"+ record._2 +")"
                conn.createStatement().execute(sql)
            })
            conn.close()
        })
    })
    ssc.start()
    ssc.awaitTermination()
}

def getConnection()={
    Class.forName("com.mysql.jdbc.Driver")
    DriverManeger.getConnection("jdbc:mysql://localhost:3306/test","root","root")
}


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值