序列化是将对象转换为字节流,本质上可以理解为将链表存储的非连续空间的数据存储转化为连续空间存储的数组中。这样就可以将数据进行流式传输或者块存储。
压缩当大片连续区域进行数据存储并且存储区域中数据重复性高的状况下,数据适合进行压缩。数组或者对象序列化后的数据块可以考虑压缩。所以序列化后的数据可以压缩,使数据紧缩,减少空间开销。 Snappy提供了更高的压缩速度,LZF提供了更高的压缩比,用户可以根据具体需求选择压缩方式。
Spark存储系统可以从以下几个维度理解整个存储系统:类接口、数据读写流程和数据通信。
- 类接口。 所有外部类都通过块管理器接口(BlockManager)对存储模块(storage)进行操作。
- 数据读写流程 数据存储分为3个层次:内存、本地磁盘和远程磁盘。在diskManager中,存储块ID(blockId)和文件路径映射。 •数据读取流程 在RDD类中,通过compute方法调用迭代器(iterator)读取某个分区(Partition)的数据。分区是逻辑概念。一个分区对应物理上的一个块(block)。一个Executor负责若干个分区。查看数据存储位置的优先级是: 1) 内存; 2) Tachyon; 3) 本地磁盘; 4) 远程磁盘 在获取远程数据时,先得到远程数据路径,然后通过块管理器工作机创建通信管理器,并从远程读取数据。 •数据写入流程
数据写入流程主要分为以下几个步骤。 1)在RDD类中,通过调用compute方法计算要写到哪个分区。 2)然后通过缓存管理器(CacheManager)调用块管理器(BlockManager),判断数据是否已经写入,如果未写则写入。 3)块管理器(BlockManager)根据指定的存储层次向相应块写入数据。并向主节点汇报存储状态。 •MemoryStore:提供Block在内存中的Block读写功能。 •DiskStore:提供Block在磁盘上以文件形式读写的功能。 •BlockManagerWorker:对远端数据的异步传输进行管理。 •ConnectionManager:提供本地机器和远端节点进行网络传输Block的功能。 (3) 数据通信 主节点和从节点之间通过Actor传送信息。 •BlockManagerMasterActor:在主节点创建,所有从节点都用于这个Actor引用,并通过这个Actor的引用向主节点传递信息。 •BlockManagerSlaveActor:在从节点创建,主节点拥有所有从节点的这个Actor引用,通过这个Actor引用向从节点传递控制信息(命令)。
块管理器(BlockManager)在内部封装块管理器Master(BlockManagerMaster),并通过BlockManagerMaster对Actor通信进行管理。各从节点的块管理器(BlockManager)对象在Spark上下文环境中(SparkEnv)中创建。在SparkEnv中也会创建其他管理组件,例如connectionManager、broadcastManager、cacheManager等。
图 RDD数据管理模型 在物理上,RDD对象实质上是一个元数据结构,存储着块、节点(Block、Node)等的映射关系,以及其他的元数据信息。数据块Block对应一个分区,若干个分区组成一个RDD。 分区是逻辑概念,变换前后的分区在物理上可能处在同一块内存。这是很重要的优化,以防止函数式数据不变性(immutable)导致的内存需求无限扩张。如果要重复使用数据(机器学习中多次迭代),可以调用cache()方法缓存数据。图3-2为RDD的数据存储模型。