什么是RDD
RDD(Resilient Distributed Dataset)叫做分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变、可分区、弹性、里面的元素可并行计算的集合
RDD允许用户在执行多个查询时显式地将工作集缓存在内存中,后续的查询能够重用工作集,这极大地提升了查询速度
RDD支持两种操作:转化操作和行动操作
Spark采用惰性计算模式,RDD只有第一次在一个行动操作中用到时,才会真正计算
属性:
一组分区(Partition)
一个计算每个分区的函数
RDD之间的依赖关系
一个Partitioner
一个列表 移动数据不如移动计算
- 每个节点可以起一个或多个Executor。
- 每个Executor由若干core组成,每个Executor的每个core一次只能执行一个Task。
- 每个Task执行的结果就是生成了下一个RDD的一个partiton。
特点:
分区:RDD逻辑上是分区的,每个分区的数据是抽象存在的
只读:RDD是只读的,要想改变RDD中的数据,只能在现有的RDD基础上创建新的RDD
依赖:RDDs通过操作算子进行转换,转换得到的新RDD包含了从其他RDDs衍生所必需的信息,RDDs之间维护着这种血缘关系,也称之为依赖
缓存:如果在应用程序中多次使用同一个RDD,可以将该RDD缓存起来,这样就加速后期的重用
checkPoint:RDD支持checkpoint将数据保存到持久化的存储中,这样就可以切断之前的血缘关系
RDD TransFormation
创建 makeRDD
删 filter distinct
改 map flatMap mapPartitions(每个分区执行一次 , 传入Iterator, 传出Iterator)
分区 coalesce repartition (切记是否需要suffer) partitionBy(自定义分区 , 根据业务减少数据倾斜)
排序 sortBy (sortByKey 完全可以简单的由sortBy实现, 第二个参数设置倒序 , 第三个参数设置分区数量 , suffer过程会重分区) 宽依赖
集合 union(并集 ,不去重) intersection(交集,去重) subtract (交集减并集) cartesian(笛卡尔积 , 形成map , 自以为无意义)
键值对 join((K,V)和(K,W)形成(K,(v,w))) reduceByKey(根据key聚合计算value) groupBykey(感觉reduceByKey更好用) mapValues(对value进行转换) keys values (取出key 和 value)
Action
reduce(func) collect() count() take(n) first(使用take(1)更好) takeOrdered(n) saveAsTextFile(path) saveAsSequenceFile(path) saveAsObjectFile(path) countByKey() foreach(func)
RDD持久化
RDD.persist 设置缓存 RDD.unpersist 清空缓存 建议使用这俩 , cache也行 RDD检查点机制 sc.setCheckpointDir("hdfs://CentOS1:9000/checkpoint") rdd.checkpoint() rdd.collect
检查点机制可以不依赖 依赖链, 缓存需要依赖
宽窄依赖
窄依赖,由于partition依赖关系的确定性,partition的转换处理就可以在同一个线程里完成,窄依赖就被spark划分到同一个stage中,而对于宽依赖,只能等父RDD shuffle处理完成后,下一个stage才能开始接下来的计算
spark划分stage:
从后往前推,遇到宽依赖就断开,划分为一个stage;遇到窄依赖就将这个RDD加入该stage中。
ShuffleMapTask和ResultTask
DAG的最后一个阶段会为每个结果的partition生成一个ResultTask,即每个Stage里面的Task的数量是由该Stage中最后一个RDD的Partition的数量所决定的,余所有阶段都会生成ShuffleMapTask;之所以称之为ShuffleMapTask是因为它需要将自己的计算结果通过shuffle到下一个stage中
广播变量和累加器
val broadcast = sc.broadcast(1 to 15) sc.makeRDD(broadcast.value) 不使用广播变量会每一个task分配一个 , 占用空间 , 使用广播变量会每一个executor 存储一个 , 节省空间 , 变量只读 , 不可写 累加器 在项目中 , 经常遇到项目调试 , 监控 , 记录一些特征值的情况 , 需要使用累加器来解决 如果直接定义变量的话 , 每个task都会持有一份该变量 , 占空间 , val a=sc.accumulator(0) sc.makeRDD(broadcast.value).map(x=>{a.add(1);x}).collect a.value