MemoryStore负责将Block存储到内存,减少对磁盘的依赖,MemoryStory依赖MemoryManager。与之相对应的是DiskStore,负责将Block存储在磁盘上。
其源码位于spark-core包下的org.apache.spark.storage.memory.MemoryStore
1 MemoryStore的内存模型
Block在内存中是以什么方式存在的呢?在MemoryStore.scala文件中定义了特质EmeoryEntry以及他的两个实现类。DeserializedMemoryEntry表示反序列化后的MemoryEntry,SerializedMemoryEntry表示序列化后的MemoryEntry。如果是非序列化,则使用DeserializedMemoryEntry保存在数组中,如果是序列化,则使用SerializedMemoryEntry保存在缓冲数组中。
private sealed trait MemoryEntry[T] {
def size: Long //Block大小
def memoryMode: MemoryMode //Block的内存模式,堆内还是堆外
def classTag: ClassTag[T] //Block的类型标记
}
private case class DeserializedMemoryEntry[T](
value: Array[T],
size: Long,
classTag: ClassTag[T]) extends MemoryEntry[T] {
val memoryMode: MemoryMode = MemoryMode.ON_HEAP
}
private case class SerializedMemoryEntry[T](
buffer: ChunkedByteBuffer,
memoryMode: MemoryMode,
classTag: ClassTag[T]) extends MemoryEntry[T] {
def size: Long = buffer.size
}
相比于MemoryManager,MemoryStore更加宏观,分为Block存储占用(存储为MemoryEntry),这块我们称为blocksMemoryUsed;和当前将要被展开的Block数据占用的内存,称为currentUnrollMemory;以及未被使用的内存三部分。在MemoryStore中,存储内存/执行内存的软边界,堆内存/堆外内存的隔阂都是透明的。展开操作的内存必须是将整个Block内存提前申请好的,防止向内存真正写入数据的时候发生内存溢出。
说白了,Unroll所申请的这部分其实并没有被真正的占用,是先过一遍partition的数据,看一下全部cache到内存需要占用多大,然后向MemoryManager预约这么大的内存,如果完全足够,那么才将数据完全存储到内存中,这时候占用内存是StorageManager中的。
网友评论