Spark Storage之MemoryStore

来源:互联网 发布:在淘宝上买了二手钢琴 编辑:程序博客网 时间:2024/06/07 20:27

概要

Storage模块使用BlockStore存储数据,BlockStore是抽象类,其实现类之一MemoryStore负责内存数据的存储。

存储

BlockStore只定义了操作数据的抽象方法,MemoryStore继承BlockStore实现了相关方法,类图如下

内存中的数据使用MemoryEntry对象的value属性存储,并加了数据大小以及是否序列化的描述信息,MemoryEntry定义如下

(注:scala中Any类型等同于Java中的Object)

MemoryStore使用LinkedHashMap维护存储数据的MemoryEntry对象,如下

关于LinkedHashMap的使用补充以下两点

  • LinkedHashMap内存使用双向链表维护数据的顺序(访问顺序或插入顺序),第三个参数为true时维护访问顺序,每次访问的数据被移至双向链表首位。
  • LinkedHashMap的value为MemoryEntry对象,Key为BlockId,BlockId有三个主要实现类,RDDBlockIdShuffleBlockIdBroadcastBlockId,分别存储RDD、Shuffle中间结果和Broadcast。

Serialize & Deserialize

内存中存储的数据有两种格式,即SerializeDeserialize,通过StorageLevel对象设置,例如MEMORY_ONLYMEMORY_ONLY_SER,后者表示内存中存储的是Serialize数据。

MemoryStore使用MemoryEntry对象的value属性存储数据,value的类型为Any,这是抽象类型,其实际存储类型和SerializeDeserialize的对应关系如下

StorageLevel Type 解释 Serialize java.nio.ByteBuffer 例如StorageLevel为MEMORY_ONLY_SER时,原始数据若为Java对象(即Deserialize格式),会先被序列化为byte[],然后封装为ByteBuffer,存储到MemoryEntry对象的value属性中 Deserialize Array[Any] 例如StorageLevel为MEMORY_ONLY时,若原始数据为byte[],先反序列化为Array[Any],使用MemoryEntry对象的value属性存储,反序列化过程涉及到unroll及内存是否足够问题

Method

putXXX

BlockStore定义了三个存储数据的方法,putBytesputArrayputIterator,从方法名可以判断出其输入的数据源格式不同,更多实现细节总结如下

putBytes putArray putIterator 输入数据格式 java.nio.ByteBuffer(Serialize) Array[Any](Deserialize) Iterator[Any] Serialize(用户设置的StorageLevel) 调用tryToPut Serializer的serializeStream方法序列化Array[Any]并封装为ByteBuffer,调用tryToPut 调用unrollSafely方法,尝试将数据安全加载到内存(避免OOM),若内存充足则加载到内存成功,unrollSafely返回Array[Any],接着调用putArray方法;若内存不足,unroll失败,交给DiskStore处理(磁盘存储) Deserialize(用户设置的StorageLevel) Serializer的deserializeStream方法将ByteBuffer转换为Iterator[Any],调用putIterator 调用tryToPut

从上表可以看出,当putXXX方法的输入数据格式(Serialize或Deserialize)与StorageLevel设置相同时,调用tryToPut方法,否则会进行格式的转换,再调用相应方法。

tryToPut

putBytesputArrayputIterator方法底层调用tryToPut方法,其主要逻辑如下

  1. 向MemoryManager申请所需要内存,如果内存不足,会尝试驱逐内存中现有数据以获得更多内存。
  2. 如果申请到足够的内存,数据存储MemoryEntry对象中,交给LinkedHashMap管理。
  3. 内存不足,清除数据,相关信息封装为droppedBlocks返回给调用者。

unrollSafely

putIterator方法处理的数据为Iterator[Any],此时不能直接在内存中处理数据,可能导致OOM,unrollSafely处理的方式是,每处理16个对象check内存使用情况,若内存足够,最终返回Array[Any],交给putArray方法处理,否则,将Iterator[Any]封装为PutResult,交由调用者处理。

总结

介绍MemoryStore的实现及几个重要方法。

原创粉丝点击