spark为什么这么快

作者:张科

网上答案都是千篇一律:数据都在内存所以快,是有误区的。

聊 spark 必须聊 rdd, rdd 全英文 Resilient Distributed Datasets,搞懂这三个单词就完事了其实。

null

Resilient:能复原的,弹回的,有弹性的。谈谈 spark 的内存机制,spark 的内存整体分外堆内内存和对外内存,而在内存的使用上又分为数据内存和运行内存,就是数据存储和程序运行。

堆内内存的管理并不完全依托与 jvm,jvm 对于所有的对象都要序列化为二进制字节流,本质上是就是将不连续的空间转换为连续的空间并且需要的空间也会小,相应的也就有反序列化。序列化的方式可以节省空间,但增加了读取时候计算的开销。spark 的对象由于是字节流的形式,其占用的内存大小可直接计算,而对于非序列化的对象,其占用的内存是通过周期性地采样近似估算而得,即并不是每次新增的数据项都会计算一次占用的内存大小,这种方法降低了时间开销但是有可能误差较大。

因为堆内内存会有诸多限制,所以 spark 通过 JDK Unsafe API 实现堆外内存。Spark 可以直接操作系统堆外内存,减少了不必要的内存开销,以及频繁的 GC 扫描和回收,提升了处理性能。堆外内存可以被精确地申请和释放,而且序列化的数据占用的空间可以被精确计算,所以相比堆内内存来说降低了管理的难度,也降低了误差。

再说说数据内存和运行内存。spark 用的是动态管理机制。数据内存和运行内存可以相互借对方的内存使用。当内存都不足的时候就只能落地到盘了。俗话说有借有还,他两却不一样,数据内存可以有借有还,而运行内存只能有借无还,因为运行内存存在很多复杂的逻辑,不能随意的释放掉。

Distributed 分布式,就指的是 spark 的 partition,spark 就是将一整块特别大的数据按照一定规则分到各个机器上,然后将代码也发送过去,每个分区执行完逻辑后,最后将结果汇总到一块就是最终的结果,数据的分发规则也是一个重点,有时会出现数据倾斜就是因为分发不均衡,如果大部分数据数据都在一个机器上计算,那分布式计算就没有什么意义了,所以在处理数据的时候要避免数据倾斜,数据倾斜也分为好多种,计算时候的倾斜,存储时候的倾斜等等,在这里就不细说了。

Datasets spark 的数据处理快还要得益于他数据的处理方式,就像下电影一样,一般先下下来在看,总没有一遍下一遍看快啊,也是他为什么称为 pipeline 处理方式。但是要注意的是,并不是每处理完一个 rdd 就交给这个下一个节点,一般是小批量的方式传递,这一般也是优化考虑的地方。

lineage spark 的血缘关系也是一大亮点,每一个上面的 rdd, 不管他经历了什么 map, group 等等,spark 都会知道他的来龙去脉,当出现问题的时候,很容易根据血缘关系重新计算出数据。

因为 spark 通常处理数据少则几分钟多则几小时,将它的执行图比如一张蜘蛛网,如果某一个点断了,整张蜘蛛网都会收到牵扯,引起这个点断了的因素有很多,网络原因,机器原因等等。这个时候假如需要从头开始计算每个节点的数据,那就会特别的耗时间,但是只修复这一个点就能解决问题,不用在重新计算已经计算好的数据那效率肯定很高了,这就是 spark 自动容错自动恢复的优点,这些中间数据通过 checkpoint 来落到盘中以便后续的恢复。具体的血缘关系的划分,根据宽窄依赖划分等,就不细说了。

Tags: