一 spark

1 rdd是通过装饰者模式形成的一系列函数的依赖关系,可分区、并行;其实不是数据而是计算,只不过通常还是叫数据集。

2 窄依赖是指一个父rdd的partition做多被一个子rdd 的partition引用,独生子女。

3 application 初始化一个sparkContext即生成一个Application。

job 一个action算子会生成一个job。

stage 宽依赖来确定前后两个stage, 是一个taskset。

task  一个分区形成一个task。

4 spark 三大数据结构,rdd 广播变量  累加器

rdd   

累加器(只写) 不是只有加法的概念,还有字符串拼接甚至更复杂的逻辑。 自定义累加器可以自己写累加器定义并且注册到sparkContext上,基础累加器类型可以直接由sparkContext来定义即可。

val accumulator : LongAccumulator = sc.longAccumulator
dataRdd.foreach{
  case i =>{
    accumulator.add(i)
  }
}

广播变量(只读),用来高效分发较大的对象,向所有工作节点发送一个较大的只读值,以供一个或者多个spark操作使用。

1)默认方式,它会极大的系统的内存,我们可以假设一个集群中有1024个task,这个共享变量大小假设为1M,那么就会去复制1024份到集群上去,这样就会有1个G的数据在网络中传输

2)广播变量的方式,如果是1024个task需要消耗1G内存,但是如果我们有50个executor来平分这些task,那么只需要50个副本即可。具体解释如下:当每一个task需要使用这个变量的时候都会拷贝一份。如果使用广播变量,首先该广播变量会拷贝一份副本到Driver中,当每一个executor的task使用到该变量时,首先会去每个executor的BlockManager中去检查是否有该变量的副本,如果没有,接着会去Driver中去拷贝一份副本到BlockManager中,然后供该executor中的每一个task使用,到下一个executor的task需要使用这个变量时,它的BlockManager可以去Driver中拷贝副本,也可以去距离比较近的executor的BlockManager中去拷贝。(每一个executor中的BlockManager的作用是负责管理每一个executor对应的内存和磁盘的数据。)

5 sparksql

主要有两种数据结构 DataFrame   DataSet 由sparkSession创建。rdd增加结构变为DataFrame (只有顺序差别),在增加类型变为DataSet (有类型属性了)

dataframe产生的三种方法:1)通过读取数据源(文件、数据库、消息队列) 2)从存在的rdd进行转换  3)从hive table查询返回。

sparksql中SparkSession取代sparkContext。

val sparkConf = new SparkConf().setMaster("local[*]").setAppName("my appliaction")
val zclSpark: SparkSession = SparkSession.builder().config(sparkConf).getOrCreate()
import zclSpark.impilcits._  //这里zclSpark不是包的名称,而是sparkSession对象名称
//创建rdd
val rdd: RDD[(Int, String, Int)] = zclSpark.sparkContext.makeRDD(List(  (1,"zhangsan",20),(2,"lisi",30), (3,"wangwu",40)  ))
//转换为df
val df:DataFrame = rdd.toDF("id","name","age")
//转换为ds 需要类型信息string int等,增加类型约束
val ds:Dataset[User] = df.as[User]
//转换为df
val df1:DataFrame = ds.toDF()
//转换为rdd,内部为row行类型,需要通过顺序索引来获取内部具体对象。
val ds1:RDD[ROW] = df1.rdd
rdd1.foreach(row=>{println(row.getString(1))})


//伴生对象,既有结构,又有类型
case class User(id:int, name:String, age:int)
//另外一种方式就是rdd如果直接有结构类型两个信息,就可以直接转换为dataset
//创建rdd
val rdd: RDD[(Int, String, Int)] = zclSpark.sparkContext.makeRDD(List(  (1,"zhangsan",20),(2,"lisi",30), (3,"wangwu",40)  ))

val userRdd:RDD[User] = rdd.map{
  case (id, name, age) =>{
    User(id,name,age)
  }
}
//如果rdd内部包含类型结构,可以直接toDS转换为Dataset
val userDS : Dataset[User]= userRdd.toDS()
//注意这里转换后rdd的内部类型还是内部类User不是上一个的ROW行类型
val rdd1:RDD[User] = userDS.rdd
rdd.foreach(println)

flink 怎样累加数据 flink 累加器_flink 怎样累加数据

 

二 sparkstreaming

1 微批处理

2 状态的概念,由checkpoint实现

不同批次之间,只计算自己批次的数据,比如无状态的算子map flatmap reducebykey groupbykey等

但是可以通过状态将不同批次数据联系起来,比如updateStateByKey, state本质上还是Checkpoint机制来实现的。

举例如下,计算单词数量,不同批次的数据可以通过updateStateByKey来维护相同key的单词的数量,seq这个数组就是本批次相同key的单词数量的int数组,seq.sum就是计算本批次某个单词的总的数量。buffer就是状态维护的目前为止某个单词总的数量。

mapDstream.updateStateByKey{
  case(seq, buffer)=>{
    val sum = buffer.getOrElse(0)+seq.sum
    Option(sum)  //更新新的状态数值
  }
}

3 也有窗口函数,窗口大小最少是streaming设定的批次周期,窗口可以大于批次倍数,但肯定不能小于。

这时候计算的结果如果不用状态关联,计算的结果就是窗口时间范围内的数据,而不是批次内部的数据。

kafkaDStream.window(Seconds(10),Seconds(5));//假设批次为5s,都应该是整数倍