Spark也有數(shù)據(jù)本地化的概念(Data Locality),這和MapReduce的Local Task差不多,如果讀取HDFS文件,Spark則會根據(jù)數(shù)據(jù)的存儲位置,分配離數(shù)據(jù)存儲最近的Executor去執(zhí)行任務(wù)。
這么理解沒錯,我搭建的Spark集群情況是這樣:
15臺DataNode節(jié)點的HDFS集群,我在每個DataNode上都部署了一個Spark Worker,并且,啟動Spark Application的時候,每個Worker都有一個Executor,這樣理論上來說,只要讀取HDFS文件,Spark都可以使用本地任務(wù)來讀取(NODE_LOCAL)。
在$SPARK_HOME/conf/slaves文件中配置了每個Worker的hostname,之后在Master上,執(zhí)行$SPARK_HOME/sbin/start-slaves.sh來啟動Workers,啟動之后集群如圖顯示:
需要大數(shù)據(jù)學(xué)習(xí)資料和交流學(xué)習(xí)的同學(xué)可以加大數(shù)據(jù)學(xué)習(xí)群:724693112 有免費資料分享和一群學(xué)習(xí)大數(shù)據(jù)的小伙伴一起努力

進入spark-sql,從hive中掃描一張表,執(zhí)行情況如下:

奇怪的是,所有讀取HDFS文件的Task Locality Level全部是ANY,也就是說,沒有一個使用NODE_LOCAL本地化任務(wù),這樣導(dǎo)致集群的網(wǎng)絡(luò)消耗非常大(因為所有的數(shù)據(jù)都要經(jīng)網(wǎng)絡(luò)拷貝一遍),如圖,后面那個峰值是執(zhí)行任務(wù)的網(wǎng)絡(luò)情況:

直接說原因和解決辦法吧。
請注意最上面集群情況的圖中,Worker Id和Address中都使用的IP地址作為Worker的標識,而HDFS集群中一般都以hostname作為slave的標識,這樣,Spark從HDFS中獲取文件的保存位置對應(yīng)的是hostname,而Spark自己的Worker標識為IP地址,兩者不同,因此沒有將任務(wù)的Locality Level標記為NODE_LOCAL,而是ANY。奇怪的是,我在Spark的slaves文件中都配置的是hostname,為何集群啟動后都采用了IP地址?最大的可能是/etc/hosts文件的配置。
大數(shù)據(jù)學(xué)習(xí)交流群:724693112 歡迎想學(xué)習(xí)大數(shù)據(jù)和需要大數(shù)據(jù)學(xué)習(xí)資料的同學(xué)來一起學(xué)習(xí)。
解決辦法是:沒有采用slaves文件+start-slaves.sh的方式啟動,而是每臺Worker單獨啟動,
使用命令:$SPARK_HOME/sbin/start-slave.sh -h ,這樣啟動之后,Spark WEBUI中Worker Id和Address中都以hostname來顯示了,如圖:

再次進入spark-sql,執(zhí)行同樣的任務(wù),所有的Task Locality Level都是NODE_LOCAL,沒有網(wǎng)絡(luò)傳輸,速度比之前快了好幾倍。

這才是期望的結(jié)果,至于導(dǎo)致salves文件中配置的明明是hostname,為何Spark集群中解析成IP地址的原因,后續(xù)再查吧。