(ⅱ)変換演算子とフォールトトレランスをSparkStreaming

用いられる変換演算子

変換:DSTREAM - > DSTREAMすなわち配列[RDD] - >配列[RDD]
RDD変換:RDD - > RDD

ここに画像を挿入説明

package transformation

import org.apache.spark.SparkConf
import org.apache.spark.streaming.{Seconds, StreamingContext}

object TransformationDemo {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("11").setMaster("local[*]")
    val ssc = new StreamingContext(conf, Seconds(5))
    ssc.sparkContext.setLogLevel("ERROR")

    // 数据源DStream 注意:hostname虚拟机的IP地址
    val lines = ssc.socketTextStream("localhost", 8888)

    //********************************************************************
    // map转换函数
    /*
    lines
      .map((_,true))  // 将一种类型映射为另外的一种类型
      // 将tuple2中的第一值 按照"," 展开
      .flatMap(_._1.split(","))      // 将一个内容展开为多个内容
      .filter(_.equals("Hello"))    // 保留符合条件的结果
      .repartition(3)  // 调整并行度 分区数量可大可小
      .print()
    */
    //********************************************************************

    //********************************************************************
    // union 合并转换函数
    /*
    val d1 = ssc.socketTextStream("localhost",7777)
    val d2 = ssc.socketTextStream("localhost",6666)

    // 合并操作要求DStream的元素类型必须一致
    val d3 = d1.union(d2)
    d3.print()
    */
    //********************************************************************

    //********************************************************************
    // count 转换函数  统计每一个微批RDD中元素数量
    /*
    val d1 = ssc.socketTextStream("localhost",7777)
    val d2 = d1.count()
    d2.print()
     */
    //********************************************************************

    //********************************************************************
    // reduce 转换函数  计算每一个微批RDD中的结果
    /*
    val d1 = ssc.socketTextStream("localhost", 7777)
    // "1" "2" "3" "4" "5"
    d1
      // "1" "2" "3" "4" "5" ---> 1 2 3 4 5
      .map(str => str.toInt)
      // 1+2 =3
      // 3+3 =6
      // 6+4 =10
      // 10+5 = 15
      .reduce(_ + _)
      .print()
     */
    //********************************************************************

    //********************************************************************
    // countByValue  统计每一个微批中相同元素的数量  返回(元素,次数)
    /*
    val d1 = ssc.socketTextStream("localhost", 7777)
    d1
      .flatMap(_.split(","))
      .countByValue()
      .print()
     */
    //********************************************************************

    //********************************************************************
    // reduceByKey 对一个DStream[(k,v)] 返回相同K的v计算结果
    /*
    val d1 = ssc.socketTextStream("localhost", 7777)
    // a,a,a,b,c
    d1
      .flatMap(_.split(","))
      .map((_, 1L))
      .reduceByKey((v1, v2) => v1 + v2, numPartitions = 2)
      .print()
    */
    //********************************************************************

    //********************************************************************
    // join 连接操作  对DStream[(k,v)]和DStream[(k,w)]连接 返回DStream[(k,(v,w))]
    /*
    val d1 = ssc.socketTextStream("localhost", 7777).map((_, 1))
    val d2 = ssc.socketTextStream("localhost", 6666).map((_, 1))
    // 内连接  同样支持左、右、全外连接
    d1
      //.join(d2)
      .leftOuterJoin(d2)  // (k,(v,Option)   //Some or None
      .print()
     */
    //********************************************************************

    
    // cogroup 共同分组方法  对DStream[(k,v)]和DStream[(k,w)]分区,返回DStream[(k,Seq[v],Seq[w])]
    // d1: (userId,name)
    // d2: (userId,订单)
    // d1.cogroup(d2)
    // (userId,(Seq(name),Seq(订单集合)))
    //********************************************************************
    /*
    val d1 = ssc.socketTextStream("localhost", 7777).map((_, 1))
    val d2 = ssc.socketTextStream("localhost", 6666).map((_, 1))
    d1
      .cogroup(d2)
      .print()
    */
    //********************************************************************
    

    //********************************************************************
    // transform  将DStream转换为RDD的操作并且返回一个新的DStream
    val d1 = ssc.socketTextStream("localhost", 7777)
    // 数据采样 sample
    d1
      .transform(rdd => {
        // rdd的转换操作 如果以后遇到DStream 函数无法处理的需求时,也可以将转换为RDD的操作
        // rdd.map((_, 1))
        rdd.sample(true,0.3)
      })
      .print()
    //********************************************************************
    // 启动应用
    ssc.start()

    ssc.awaitTermination()
  }
}

変換演算子ステートフル

updateStateByKeyFUNC):**(常に状態データを維持するために更新され、新たな情報の使用を許可する鍵の更新状況(状態)、に基づいて、更新の合計額

package transformation.state

import org.apache.spark.SparkConf
import org.apache.spark.streaming.{Seconds, StreamingContext}

object StateDemo {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setMaster("local[*]").setAppName("word count")
    val ssc = new StreamingContext(conf, Seconds(5))
    ssc.sparkContext.setLogLevel("ERROR")
    val lines = ssc.socketTextStream("localhost", 7777)

    // 必须设置检查点checkpoint 本地状态(内存) + 远程状态(checkpoint)
    // 启动hdfs服务 + 添加虚拟参数-DHADOOP_USER_NAME=root
    ssc.checkpoint("hdfs://xxx:9000/checkpoint")

    // 实现有状态的计算
    lines
      .flatMap(_.split(","))
      .map((_, 1))
      // 参数为:状态更新的匿名函数
      // values: 当前微批中的key相同的value的序列集合
      // state: 累积的状态数据
      .updateStateByKey((values: Seq[Int], state: Option[Int]) => {
        // 使用当前微批的统计结果 + state数据 => 最新的计算结果
        // 当前微批中key相同的value的数量
        val newState = values.size + state.getOrElse(0)
        // 累积的最新的状态数据
        Some(newState)
      })
      .print()

    ssc.start()
    ssc.awaitTermination()
  }
}

mapWithState: ステータスを更新するための別の方法に比べてupdateStateByKey性能リフト10回(合計量の更新)、増分更新

// 必须设置检查点checkpoint 本地状态(内存) + 远程状态(checkpoint)
    // 启动hdfs服务 + 添加虚拟参数-DHADOOP_USER_NAME=root
    ssc.checkpoint("hdfs://xxx:9000/checkpoint")

    // 实现有状态的计算
    lines
      .flatMap(_.split(","))
      .map((_, 1L))
      // 参数:StateSpec
      // StateSpec.function方法 ---> StateSpec
      // state: k=word v=累积次数
      // key:单词  value:次数  state:历史状态
      .mapWithState(StateSpec.function((key: String, value: Option[Long], state: State[Long]) => {
        var newCount = 0L;
        // key存在历史状态数据
        if (state.exists()) {
          newCount = state.get() + value.get
        } else {
          newCount = 1
        }
        // newCount更新State中历史状态数据
        state.update(newCount)
        // 将累积的结果作为DStream中的元素返回
        (key, newCount)
      }))

フォールトトレランス

チェックポイントのチェックポイント

ストリーミングアプリケーションのためにクロック7 * 24時間運転を計算し、そのプログラムの論理エラー(:JVMベンの崩壊、システムエラー、外部要因等)とは無関係に適合させることができることができなければなりません。ストレージシステム(HDFS)、障害が発生したタイムリーな回復トレラント・フォールトするのに十分な情報を保存するには、この問題を解決するために、スパークストリーミング必要。チェックポイントデータの2種類があります。

  • チェックポイントのメタデータメタデータのチェックポイント):ストリームコンピューティングアプリケーション
    • 設定:情報の構成は、ストリーミングアプリケーションsparkconf
    • DSTREAM操作機能:変換機能や操作機能
    • 不完全な状態でBtaches:マイクロバッチデータが完了し、未処理
  • チェックポイントデータ(データがチェックポイント):RDDは、信頼性の高いストレージシステムを製造するために保存され、切断リンクに依存

= +チェックポイント・データ・アプリケーション情報

チェックポイントのフォールトトレランスで

package transformation.state

import org.apache.spark.SparkConf
import org.apache.spark.streaming.{Seconds, State, StateSpec, StreamingContext}

object StateDemo3 {
  def main(args: Array[String]): Unit = {
    // 使用检查点容错处理
    // 获取或者创建一个SSC
    // 参数一:checkpoint path  参数二:匿名函数 Function0 ---> SSC
    val ssc = StreamingContext.getOrCreate(
      "hdfs://xxx:9000/checkpoint",
      () => {
        // 内容是什么???
        val conf = new SparkConf().setMaster("local[*]").setAppName("word count")
        val ssc = new StreamingContext(conf, Seconds(5))
        ssc.sparkContext.setLogLevel("ERROR")
        val lines = ssc.socketTextStream("localhost", 7777)

        // 必须设置检查点checkpoint 本地状态(内存) + 远程状态(checkpoint)
        // 启动hdfs服务 + 添加虚拟参数-DHADOOP_USER_NAME=root
        ssc.checkpoint("hdfs://xxx:9000/checkpoint")

        // 实现有状态的计算
        lines
          .flatMap(_.split(","))
          .map((_, 1L))
          // 参数:StateSpec
          // StateSpec.function方法 ---> StateSpec
          // state: k=word v=累积次数
          // key:单词  value:次数  state:历史状态
          .mapWithState(StateSpec.function((key: String, value: Option[Long], state: State[Long]) => {
            var newCount = 0L;
            // key存在历史状态数据
            if (state.exists()) {
              newCount = state.get() + value.get
            } else {
              newCount = 1
            }
            // newCount更新State中历史状态数据
            state.update(newCount)
            // 将累积的结果作为DStream中的元素返回
            (key, newCount)
          }))
          .print()
        ssc
      }
    )
    ssc.start()
    ssc.awaitTermination()
  }
}
公開された24元の記事 ウォンの賞賛1 ビュー495

おすすめ

転載: blog.csdn.net/Mr_YXX/article/details/105034913