Once a SparkConf object is passed to Spark, it is cloned and can no longer be modified by the user.
也就是說一旦設置完成SparkConf,就不可被使用者修改
對於單元測試,您也能夠調用SparkConf(false)來跳過加載外部設置,並得到相同的配置,不管系統屬性如何。
我們再看看setMaster()和setAppName()源碼:
根據上面的解釋,setMaster主要是鏈接主節點,若是參數是"local",則在本地用單線程運行spark,若是是 local[4],則在本地用4核運行,若是設置爲spark://master:7077,就是做爲單節點運行,而setAppName就是在web端顯示應用名而已,它們說到底都調用了set()函數,讓咱們看看set()是何方神聖
logDeprecation(key)是日誌輸出函數,防止輸入參數名無效, 看看settings,是個HashMap結構,追溯一下:
果真,是個ConcurrentHashMap對象,ConcurrentHashMap主要做用是解決多線程併發下數據段訪問效率,該類相對於hashMap而言具備同步map中的數據,對於hashTable而言,該同步數據對於併發程序提升了極高的效率,因此在使用緩存機制的時候若是對map中的值具備高併發的狀況的話,那麼咱們就須要使用ConcurrentHashMap,ConcurrentHashMap中主要實體類就是三個:ConcurrentHashMap(整個Hash表),Segment(桶),HashEntry(節點)
,CurrentHashMap的初始化一共有三個參數,一個initialCapacity,表示初始的容量,一個loadFactor,表示負載參數,最後一個是concurrentLevel,表明ConcurrentHashMap內部的Segment的數量,ConcurrentLevel一經指定,不可改變,這也是爲何SparkConf配置好了就沒法更改的緣由。
ConcurrentHashMap應用了鎖分段技術,
HashTable容器在競爭激烈的併發環境下表現出效率低下的緣由,是由於全部訪問HashTable的線程都必須競爭同一把鎖,那假如容器裏有多把鎖,每一把鎖用於鎖容器其中一部分數據,那麼當多線程訪問容器裏不一樣數據段的數據時,線程間就不會存在鎖競爭,從而能夠有效的提升併發訪問效率,這就是ConcurrentHashMap所使用的鎖分段技術,首先將數據分紅一段一段的存儲,而後給每一段數據配一把鎖,當一個線程佔用鎖訪問其中一個段數據的時候,其餘段的數據也能被其餘線程訪問。
另外,若是ConcurrentHashMap的元素數量增長致使ConrruentHashMap須要擴容,ConcurrentHashMap是不會增長Segment的數量的,而只會增長Segment中鏈表數組的容量大小,這樣的好處是擴容過程不須要對整個ConcurrentHashMap作rehash,而只須要對Segment裏面的元素作一次rehash就能夠了。
SparkSession: SparkSession實質上是SQLContext和HiveContext的組合(將來可能還會加上StreamingContext),因此在SQLContext和HiveContext上可用的API在SparkSession上一樣是可使用的。SparkSession內部封裝了sparkContext,因此計算其實是由sparkContext完成的。
val sparkSession = SparkSession.builder
.master("master")
.appName("appName")
.getOrCreate()
或者
SparkSession.builder.config(conf=SparkConf())
上面代碼相似於建立一個SparkContext,master設置爲"xiaojukeji",而後建立了一個SQLContext封裝它。若是你想建立hiveContext,可使用下面的方法來建立SparkSession,以使得它支持Hive(HiveContext):
val sparkSession = SparkSession.builder
.master("master")
.appName("appName")
.enableHiveSupport()
.getOrCreate()
//sparkSession 從csv讀取數據:
val dq = sparkSession.read.option("header", "true").csv("src/main/resources/scala.csv")
getOrCreate():有就拿過來,沒有就建立,相似於單例模式:
s1 = SparkSession().builder.config("k1", "v1").getORCreat()
s2 = SparkSession().builder.config("k2", "v2").getORCreat()
return s1.conf.get("k1") == s2.conf.get("k2")
True