You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
if (useOffHeap) {
require(!useDisk, "Off-heap storage level does not support using disk")
require(!useMemory, "Off-heap storage level does not support using heap memory")
require(!deserialized, "Off-heap storage level does not support deserialized storage")
require(replication ==1, "Off-heap storage level does not support multiple replication")
}
里面有个很有意思的方法,toInt
deftoInt:Int= {
varret=0if (_useDisk) {
ret |=8
}
if (_useMemory) {
ret |=4
}
if (_useOffHeap) {
ret |=2
}
if (_deserialized) {
ret |=1
}
ret
}
objectAextendsApp{
val_useDisk=trueval_useMemory=falseval_useOffHeap=falseval_deserialized=falsedeftoInt:Int= {
varret=0if (_useDisk) {
ret |=8
}
if (_useMemory) {
ret |=4
}
if (_useOffHeap) {
ret |=2
}
if (_deserialized) {
ret |=1
}
ret
}
println(Integer.toBinaryString(toInt))//1000,二进制的8
}
spark的存储
类的全名为 org.apache.spark.storage.StorageLevel
class相关
首先该类主构造器中定义了5个属性:
由于并不希望所有的东西都被序列化,或者说在对象还原之后,内部的子对象会重新创建而不需要将该子对象序列化,所以这里用有着
readExternal
和writeExternal
方法的Externalizable
接口代替Serializable
,在序列化和反序列化时会调用对应的方法再看辅助构造器:
一个是私有的,一个是对外开放的,私有的那个过一会再说怎么用,现在先卖个关子
接下来是一些方法:
这里明确告诉我们replication要小于40,而useOffHeap的使用主要是避免一些
jvm gc
和节约jvm
内存,注意如果是useOffHeap
,那么将不支持useDisk
和useMemory
,也不支持deserialized
,同时replication
要等于1,源代码是:里面有个很有意思的方法,toInt
这个方法主要是利用二进制数实现一个使用存储的判等,如果使用
_useDisk
,最终的ret是1000
:那clone和equals方法也容易理解
而有效性检查则是
也就是只要
replication
大于0以及使用了内存、磁盘或者OffHeap
的任意一种就可以接下来查看刚才接口中还未实现的两个方法:
先看序列化时候调用的
writeExternal
先介绍
避免了每次去catch
IOException
,而对代码块进行封装,这里调用toInt去保存此时的关于
useDisk,useMemory,useMemory
的状态,比如如果是useDisk,其他为false,那么则会写入8,也就是二进制的1000
,不得不佩服设计的巧妙,同时也将replication作为第二个字节写入了,这样就保存了此时的对象状态下面进行反序列化
如果我们在序列化阶段写入的是8,那么此时flags就是8,那么8与8进行
&
操作结果将是8,也就是1000
,是不等于0的,所以_useDisk为true,其他部分进行&
操作是false,所以能在反序列化的时候得到正确的值最后看一下描述以及toString
这个也没啥介绍的,比较直观
object
如果是DISK_ONLY,那么则构建的是
new StorageLevel(true, false, false, false,1)
,也就是useDisk属性为true,其余为false,replication
为1,使用默认值,在这里省略为:new StorageLevel(true, false, false, false)
同样我们知道了如果是
replication
为2,则是DISK_ONLY_2
,以此类推而fromString方法主要使用模式匹配选择上述策略
接着看两个私有方法,一个用了线程安全的
ConcurrentHashMap
构建了一个cache,另一个则使用putIfAbsent
的原子性操作去修改和或获取level,这个方法类似put,但只有当不含有该key时才能添加进去,如果已经包含该key,则会保存现有值最后介绍几个apply方法:
这是源码,但其实我们发现注释有问题,我给出了中文注释
java api:
这个也是很容易理解的,最后我们看一下官方的使用建议
使用
fast serializer
,但读取的cpu使用率更高replication
=2Tachyon
中用序列化格式存储rdd,相比MEMORY_ONLY_SER,OFF_HEAP减少垃圾回收的开销,使得executors
更小以及共享内存池。这在高并发环境下有吸引力。此外,由于rdd驻留在Tachyon
中,executor的崩溃不会造成数据的丢失,这种模式下,Tachyon
中的内存是可废弃的,因此,Tachyon
并不会尝试去重建从内存中清除的块。使用建议:
优先使用默认方案,如果内存不够则使用MEMORY_ONLY_SER来节约空间,不到万不得已不使用disk,除非进行大数据量操作
The text was updated successfully, but these errors were encountered: