Spark进行IO不仅考虑本地开销,还有数据在不同主机之间的开销,同时对数据的寻址方式也要改变,以应对大数据
序列化
- 用于进程间通信,不同节点之间数据传输
- 用于持久化存储到磁盘,序列化速度影响集群总体效率
在默认情况下,Spark采用Java的ObjectOutputStream序列化一个对象。该方式适用于所有实现了java.io.Serializable的类。Java序列化非常灵活,但是速度较慢。Spark也能使用Kryo序列化对象。Kryo不但速度极快,而且产生的结果更为紧凑(通常能提高10倍)。Kryo的缺点是不支持所有类型
压缩
- 序列化后的数据进行压缩,减少空间开销
- 大片连续区域进行数据存储并且存储区域中数据重复性高的状况下,数据适合进行压缩节省空间
Spark采用两种压缩算法,snappy和LZF,可以自定义压缩库
Snappy压缩速度更快,LZF压缩比更高
块管理
RDD逻辑上按照Partition分块,RDD可以看作是一个分区作为数据项的分布式数组,物理上存储单位是Block,一个Partition对应一个Block,partitionId通过元数据映射到物理Block
整体IO管理分为两个层次
通信层:IO模块采用Master-Slave结构实现通信层的架构
存储层:Spark块数据需要存储到内存或者磁盘
BlockManager中的通信
主节点和从节点之间通过Actor传送消息传递命令和状态
数据读写
数据写入:
1.RDD调用compute()方法进行制定分区的写入。
2.CacheManager中调用BlockManager判断数据是否已经写入,如果未写入则写入。
3.BlockManager中数据与其他节点同步。
4.BlockManager根据存储级别写入制定的存储层。
5.BlockManager向主节点汇报存储状态。
数据读取:
在RDD类中,通过compute方法调用iterator读写某个分区(Partition),作为数据读取的入口。分区是逻辑概念,在物理上是一个Block。
通过BlockManager读取代码进入读取逻辑,在本地同步读取数据块,首先看能否在内存读取数据块,如果不能读取,则看能否从Tacjyon读取数据块,如果仍不能读取,则看能否从本地磁盘读取数据。如果仍不存在,再看看网络中其它节点是否有数据。
作者:Alex90
链接:https://www.jianshu.com/p/5172a83ecc36
共同学习,写下你的评论
评论加载中...
作者其他优质文章