spark為什麼這麼快
作者:張科
網上答案都是千篇一律:數據都在內存所以快,是有誤區的。
聊 spark 必須聊 rdd, rdd 全英文 Resilient Distributed Datasets,搞懂這三個單詞就完事了其實。
Resilient:能復原的,彈回的,有彈性的。談談 spark 的內存機制,spark 的內存整體分外堆內內存和對外內存,而在內存的使用上又分為數據內存和運行內存,就是數據存儲和程序運行。
堆內內存的管理並不完全依託與 jvm,jvm 對於所有的對象都要序列化為二進制位元組流,本質上是就是將不連續的空間轉換為連續的空間並且需要的空間也會小,相應的也就有反序列化。序列化的方式可以節省空間,但增加了讀取時候計算的開銷。spark 的對象由於是位元組流的形式,其佔用的內存大小可直接計算,而對於非序列化的對象,其佔用的內存是通過周期性地採樣近似估算而得,即並不是每次新增的數據項都會計算一次佔用的內存大小,這種方法降低了時間開銷但是有可能誤差較大。
因為堆內內存會有諸多限制,所以 spark 通過 JDK Unsafe API 實現堆外內存。Spark 可以直接操作系統堆外內存,減少了不必要的內存開銷,以及頻繁的 GC 掃描和回收,提升了處理性能。堆外內存可以被精確地申請和釋放,而且序列化的數據佔用的空間可以被精確計算,所以相比堆內內存來說降低了管理的難度,也降低了誤差。
再說說數據內存和運行內存。spark 用的是動態管理機制。數據內存和運行內存可以相互借對方的內存使用。當內存都不足的時候就只能落地到盤了。俗話說有借有還,他兩卻不一樣,數據內存可以有借有還,而運行內存只能有借無還,因為運行內存存在很多複雜的邏輯,不能隨意的釋放掉。
Distributed 分佈式,就指的是 spark 的 partition,spark 就是將一整塊特別大的數據按照一定規則分到各個機器上,然後將代碼也發送過去,每個分區執行完邏輯後,最後將結果匯總到一塊就是最終的結果,數據的分發規則也是一個重點,有時會出現數據傾斜就是因為分發不均衡,如果大部分數據數據都在一個機器上計算,那分佈式計算就沒有什麼意義了,所以在處理數據的時候要避免數據傾斜,數據傾斜也分為好多種,計算時候的傾斜,存儲時候的傾斜等等,在這裡就不細說了。
Datasets spark 的數據處理快還要得益於他數據的處理方式,就像下電影一樣,一般先下下來在看,總沒有一遍下一遍看快啊,也是他為什麼稱為 pipeline 處理方式。但是要注意的是,並不是每處理完一個 rdd 就交給這個下一個節點,一般是小批量的方式傳遞,這一般也是優化考慮的地方。
lineage spark 的血緣關係也是一大亮點,每一個上面的 rdd, 不管他經歷了什麼 map, group 等等,spark 都會知道他的來龍去脈,當出現問題的時候,很容易根據血緣關係重新計算出數據。
因為 spark 通常處理數據少則幾分鐘多則幾小時,將它的執行圖比如一張蜘蛛網,如果某一個點斷了,整張蜘蛛網都會收到牽扯,引起這個點斷了的因素有很多,網絡原因,機器原因等等。這個時候假如需要從頭開始計算每個節點的數據,那就會特別的耗時間,但是只修復這一個點就能解決問題,不用在重新計算已經計算好的數據那效率肯定很高了,這就是 spark 自動容錯自動恢復的優點,這些中間數據通過 checkpoint 來落到盤中以便後續的恢復。具體的血緣關係的劃分,根據寬窄依賴劃分等,就不細說了。