zoukankan      html  css  js  c++  java
  • 什么是spark(一) 分区以及和MR的区别

      什么是spark,是一个分布式计算平台,或者说是分布式计算引擎,他的职责就是将指定的数据读入到各个node的内存中,然后计算。所以spark是具有泛化性质的,只要数据源是可读入的,读到内存里面之后,处理就和数据源没有关系了,你是HBASE,kudu,还是parquet都无所谓了。

      什么是RDD,弹性分布式数据集,其实RDD是一个抽象概念,因为RDD本身不包含数据,它只包含数据描述以及对于数据的算法,比如一个sparkSQL返回的RDD其实就是一个对数据的描述,告诉各个节点的executor要处理那些数据,那么map就是算法,map里面的函数体就是算法,所以map又叫做算子。

      什么是spark分区,“需要把相同 key 的元素聚集到同一个 partition 下,所以造成了数据在内存中的重新分布,即 shuffle 操作”,简单讲就是设置数据分布,将相同key的数据分布到同一台机器;为什么要分区?首先明白分区的目的好处就是:

      1)减少了网络开销;

      2)提高并行计算度;

      前者的实现是通过将join算子和hive参数放置到同一台机器,然后让发起join的表数据推送到spark的分区节点进行运算;至于后者,每个分区都有独立的线程(每个线程执行的逻辑称之为Task);可以保持彼此独立,并行进行计算,这个也是spark的机制所在。
      但是spark的分区有俩个时间点,一个是创建的时候,通过partitionBy来指定,一个是repartition的时候;后者分区可能会引发shuffle;这提到了shuffle,什么是shuffle,就是跨节点传输;Shuffle发生有两个时间节点,一个是计算过程中,同key数据分布在不同的机器,需要进行数据传输,产生了shuffle,另外一个就是各个节点计算完毕后,向driver点汇聚,这个时候又会发生一次shuffle;后者的shuffle不可避免;前者的shuffle则是可以考虑进行优化;Mapreduce为什么会会发生shuffle,就是因为没有机制保证数据不在一台机器上面;
      基于此,spark引入了分区机制。首先看一下没有分区的场景:如果不进行分区的话,就会造成join命令执行时一台机器,大表数据分散在各个节点要想join机器汇总,小表数据也要想join机器汇总。实现分区的本质好处就是把key值相同的数据放到一台机器上面;分区有两种机制,一种是Hash,一种是Range;对于大表join小表的场景下,shuffle被极大的减少,首先分区保证了(大表)相同的key是在一台机器上面,Spark将会分析,如果join的表有分区的话,将会在在大表的机器上面执行Join,这样只需要小表shuffle数据到大表(通过key做关联),这样网络开销减小了;
      关于partition划分方式有两种:一个是有多到少,这个调用的coalesec()函数,注意设置shuffle=false,因为将单节点的多个分区合并为一个即可,不会引发shuffle;因为在代码实现上,可以看到返回的new   CoalescedRDD(this, numPartitions, partitionCoalescer),第一个参数是shuffleRDD,还是历史的rdd;这种划分方式称之为窄依赖,窄,顾名思义,在自己的节点完成即可;
      第二种由少到多,调用repartion函数;其实repartition的底层就是调用的coalesce()函数;只不过设定shuffle=true而已,这里shuffle是一定要设置为true,因为当分区数量增多之后,spark里面实现是数据分布就要发生变化,就需要对数据进行重排(默认是HashPartition);关于CoalescedRDD见下面的代码:

    1 new CoalescedRDD(
    2   new ShuffledRDD[Int, T, T](mapPartitionsWithIndex(distributePartition),
    3   new HashPartitioner(numPartitions)),
    4   numPartitions,
    5   partitionCoalescer).values


      第一个参数是shuffledRDD,看到已经是一个新的RDD,分区也是new了一个新的分区。这种划分方式又称之为宽依赖,就是分区需要多个节点协作完成;
      窄依赖跟宽依赖的区别是是否发生 shuffle(洗牌) 操作.宽依赖会发生 shuffle 操作. 窄依赖是子 RDD的各个分片(partition)不依赖于其他分片,能够独立计算得到结果,宽依赖指子 RDD 的各个分片会依赖于父RDD 的多个分片,所以会造成父 RDD 的各个分片在集群中重新分片。

      那么我们为什么要使用spark?spark使用的机制其实是和Map-Reduce是一样的。

      1. spark的任务是fork出一个线程来执行,但是mr是一个进程;

      2. mr则是每次运算之后都需要把数据写入到硬盘中;spark只是在shuffle的时候需要将数据写入到硬盘中,因为spark在Driver端生成了一个DAG,可以全局考虑数据处理(MR每个map都是独立的);

      3. spark的cache做的比mr更好,因为spark在把RDD放入cache之后,将会对其进行“unroll”,将不连续的存储转化为连续存储。

      注意,有一种观点描述spark是内存技术,这种说法是不正确的,因为spark其实是配置了内存上限,超过上限,将会基于LRU策略将内存数据进行处理(销毁,或者序列化到硬盘,基于缓存策略)。

    参考
      http://blog.csdn.net/databatman/article/details/53023818#4shuffle-%E5%92%8C-stage
      https://www.cnblogs.com/licheng/p/6822376.html

      https://0x0fff.com/spark-misconceptions/ 译文:https://www.cnblogs.com/intsmaze/p/7197420.html

  • 相关阅读:
    bootstrap实战练习中涉及的知识点(很有用哦!)
    Markdown的最常用标记符号有哪些?
    队列的插入 和出列 阻塞 时间 问题
    ArrayBlockingQueue和LinkedBlockingQueue的使用
    自己总结 :并发队列ConcurrentLinkedQueue、阻塞队列AraayBlockingQueue、阻塞队列LinkedBlockingQueue 区别 和 使用场景总结
    战斗由客户端来做,后端来验证 方式 解决 一些弊端思路
    类 文件 右下角呈现 红色小圆圈,里面有一个J 标记
    苏州儿童医保
    Error: opening registry key 'SoftwareJavaSoftJava Runtime Environment' could not find java.dll
    intellj(idea) 编译项目时在warnings 页签框里 报 “xxx包不存在” 或 “找不到符号” 或 “未结束的字符串字面值” 或 “需要)” 或 “需要;”等错误提示
  • 原文地址:https://www.cnblogs.com/xiashiwendao/p/8646456.html
Copyright © 2011-2022 走看看