Master HA
1).System File
2).Zookeeper
a).在集群的每台节点../conf/spark-env.sh 中配置:
export SPARK_DAEMON_JAVA_OPTS="
-Dspark.deploy.recoveryMode=ZOOKEEPER
-Dspark.deploy.zookeeper.url=node3:2181,node4:2181,node5:2181
-Dspark.deploy.zookeeper.dir=/sparkmaster0821"
b).在StandBy-Master节点中修改../conf/spark-env.sh:SPARK_MASTER_IP = node2
c).启动Zookeeper
d).在Alive-Master节点上启动集群:../sbin/start-all.sh
e).在StandBy-Master节点上启动StandBy-Master ../sbin/start-master.sh
d).测试。
注意:
a).这里的Master HA是针对的standAlone集群
b).主备切换过程中,不影响已经在集群中运行的程序
c).主备切换过程中,不能申请资源。
Spark shuffle
Spark1.2之前默认使用的是HashShuffle(hashPartitioner),1.2之后使用的sortShuffle(rangePartitioner)。
1).HashShuffle
a).普通机制
产生磁盘小文件的个数:
M(map task个数)*R(reduce task个数)
流程:
i).map task处理完数据之后,每个task将结果写入buffer缓存区(与reduce task个数一致),每个buffer缓冲区大小是32K
ii).每个buffer满32k,溢写磁盘,每个buffer对应磁盘一个小文件。
iii).reduce task 到不同节点拉取数据
问题:产生磁盘小文件太多?
i).写磁盘文件的对象多
ii).拉取数据读磁盘文件对象多
iii).创建对象多,容易造成gc,gc还不满足内存使用,就会OOM
OOM问题:
i).Driver端回收RDD数据
ii).Executor 端创建对象非常多,可能会有OOM(0.2 task内存)
iii).Executor 端拉取shuffle数据,如果5个task一次拉取的数据量在Executor0.2的shuffle内存中放不下
iiii).Executor端对RDD进行缓存或者广播变量的RDD数据量比较大(0.6内存)
b).合并机制(HashShuffle的优化机制)
产生磁盘小文件:
C(core 的个数)*R(reduce task个数)
过程:
与普通机制一样,只是一个core内运行的task 会公用一份buffer缓存区。实际上就是多个task共用一个Core ML,与一个task占用一个core相比,减少了。
2).SortShuffle
a).普通机制
产生磁盘小文件个数:
2*M(map task个数)
流程:
i).map task 将处理的结果写入一个5M的内存结构中
ii).SortShuffle中会估算这个内存结构大小,当下一次结果放不下时,会申请2*估计-当前
iii).如果申请的到内存,继续往数据结构中写数据,如果申请不到,溢写磁盘,每批次是1万条溢写,溢写过程中会有排序。
iv).溢写的数据在磁盘上最终形成两个文件:一个索引文件一个数据文件
v).reduce 拉取数据首先解析索引文件,再去拉取数据
b).bypass机制
产生磁盘小文件个数:
2*M(map task个数)
流程:
与普通的机制对比,少了排序。当reduce task个数小于spark.shuffle.sort.bypassMergeThreshold (默认200)会开启bypass机制。
shuffle 文件的寻址
1).MapOutputTracker:磁盘小文件
MapOutputTrackerMaster(Driver端)
MapOutputTrackerWorker(Executor端)
2).BlockManager:块管理者
BlockManagerMaster(Driver端):
DiskStore:管理磁盘数据
MemoryStroe:管理内存数据
ConnectionManager:负责连接其他BlockManager
BlockTransferService:负责拉取数据
BlockManagerSlaves(Executor端):
DiskStore:管理磁盘数据
MemoryStroe:管理内存数据
ConnectionManager:负责连接其他BlockManager
BlockTransferService:负责拉取数据
3).寻址:
a).map task处理完的数据,将结果和数据位置封装到MapStatus对象中,通过MapOutputTrackerWorker汇报给Driver中的
MapOutputTrackerMaster。Driver中掌握了数据位置。
b).reduce 端处理数据,首先向本进程中的MapOutputTrackerWorker要磁盘文件位置,再向Driver中的MapOutputTrackerMaster
要磁盘数据位置,Driver返回磁盘数据位置。
c).reduce 拿到数据位置之后,通过BlockManager中的ConnectionManager连接数据所在的节点,连接上之后,通过BlockManager
中的BlockTransferService拉取数据
d).BlockTransferService拉取数据默认启动5个task,这5个task默认一次拉取的数据量不能超过48M。
e).拉取过来的数据放在Executor端的shuffle聚合内存中(spark.shuffle.memeoryFraction 0.2),
如果5个task一次拉取的数据放不到shuffle内存中会有OOM,如果放下一次,不会有OOM,以后放不下的会放磁盘。