挑战1:数据分区分散在多个计算机系统中。

挑战2:spark处理的数据量大。

spark不仅要考虑本地主机的io开销,还要考虑数据在主机之间的传输开销。寻址方式也要改变。

1、序列化

序列化是将对象转换为字节流,本质上可以理解为将链表存储的非连续空间的数据存储转化为连续空间存储的数组中。 这样就可以将数据进行流式传输或者块存储。 相反,反序列化就是将字节流转化为对象。

序列化的目的是:不同节点间进行通信,数据持久化存储到磁盘。

在Spark中,序列化拥有重要地位。 无论是内存或者磁盘中的RDD含有的对象存储,还是节点间的传输数据,都需要执行序列化的过程。 序列化与反序列化的速度、 序列化后的数据大小等都影响数据传输的速度,以致影响集群的计算效率。 

2、压缩

当大片连续区域进行数据存储并且存储区域中数据重复性高的状况下,数据适合进行压缩。 数组或者对象序列化后的数据块可以考虑压缩。 所以序列化后的数据可以压缩,使数据紧缩,减少空间开销。

(1)在Spark-env.sh文件中配置
用户可以在启动前配置文件spark-env.sh设定压缩配置的参数。
export SPARK_JAVA_OPTS="-Dspark.broadcast.compress"
(2)在应用程序中配置
sc是SparkContext对象,conf是SparkConf对象。
val conf=sc.getConf
1)获取压缩的配置。
conf.getBoolean("spark.broadcast.compress",true)
2)压缩的配置。
conf.set("spark.broadcast.compress",true)

而物理上存储RDD是以Block为单位的,一个Partition对应一个Block,用Partition的ID通过元数据的映射到物理上的Block,而这个物理上的Block可以存储在内存,也可以存储在某个节点的Spark的硬盘临时目录,等等。

整体的I/O管理分为以下两个层次。
1)通信层:I/O模块也是采用Master-Slave结构来实现通信层的架构,Master和Slave之间传输控制信息、 状态信息。
2)存储层:Spark的块数据需要存储到内存或者磁盘,有可能还需传输到远端机器,这些是由存储层完成的。

下面的内容涉及一系列的源码,暂时还不需要看