010-69036427[email protected]
在 MapReduce 框架中,Shuffle 是連接 Map 和 Reduce 之間的橋梁,Reduce 要讀取到 Map 的輸出必須要經(jīng)過 Shuffle 這個環(huán)節(jié);而 Reduce 和 Map 過程通常不在一臺節(jié)點,這意味著 Shuffle 階段通常需要跨網(wǎng)絡(luò)以及一些磁盤的讀寫操作,因此 Shuffle 的性能高低直接影響了整個程序的性能和吞吐量。
與 MapReduce 計算框架一樣,Spark 作業(yè)也有 Shuffle 階段,通常以 Shuffle 來劃分 Stage;而 Stage 之間的數(shù)據(jù)交互是需要 Shuffle 來完成的。整個過程圖如下所示:

如果想及時了解Spark、Hadoop或者Hbase相關(guān)的文章,歡迎關(guān)注微信公共帳號:iteblog_hadoop
從上面簡單的介紹可以得到以下幾個結(jié)論:
不管是 MapReduce 還是 Spark 作業(yè),Shuffle 操作是很消耗資源的,這里的資源包括:CPU、RAM、磁盤還有網(wǎng)絡(luò);
我們需要盡可能地避免 Shuffle 操作
而目前最新的 Spark 內(nèi)置只支持一種 Shuffle 實現(xiàn):org.apache.spark.shuffle.sort.SortShuffleManager,通過參數(shù) spark.shuffle.manager 來配置。這是標準的 Spark Shuffle 實現(xiàn),其內(nèi)部實現(xiàn)依賴了 Netty 框架。本文并不打算詳細介紹 Spark 內(nèi)部 Shuffle 是如何實現(xiàn)的,這里我要介紹社區(qū)對 Shuffle 的改進。
在進行下面的介紹之前,我們先來了解一些基礎(chǔ)知識。
傳統(tǒng)的 TCP Socket 數(shù)據(jù)傳輸需要經(jīng)過很多步驟:數(shù)據(jù)先從源端應(yīng)用程序拷貝到當(dāng)前主機的 Sockets 緩存區(qū),然后再拷貝到 TransportProtocol Driver,然后到 NIC Driver,最后 NIC 通過網(wǎng)絡(luò)將數(shù)據(jù)發(fā)送到目標主機的 NIC,目標主機又經(jīng)過上面步驟將數(shù)據(jù)傳輸?shù)綉?yīng)用程序,整個過程如下:

從上圖可以看出,網(wǎng)絡(luò)數(shù)據(jù)的傳輸很大一部分時間用于數(shù)據(jù)的拷貝!如果需要傳輸?shù)臄?shù)據(jù)很大,那么這個階段用的時間很可能占整個作業(yè)運行時間的很大一部分!那么有沒有一種方法直接省掉不同層的數(shù)據(jù)拷貝,使得目標主機直接從源端主機內(nèi)存獲取數(shù)據(jù)?還真有,這就是 RDMA 技術(shù)!
RDMA(Remote Direct Memory Access)技術(shù)全稱遠程直接內(nèi)存訪問,是一種直接內(nèi)存訪問技術(shù),它將數(shù)據(jù)直接從一臺計算機的內(nèi)存?zhèn)鬏數(shù)搅硪慌_計算機,無需雙方操作系統(tǒng)的介入。這允許高通量、低延遲的網(wǎng)絡(luò)通信,尤其適合在大規(guī)模并行計算機集群中使用(本段摘抄自 維基百科 - 遠程直接內(nèi)存訪問)。RDMA 有以下幾個特點:
Zero-copy
直接硬件接口(Direct hardware interface),繞過內(nèi)核和 TCP / IP 的 IO
亞微秒延遲
Flow control and reliability is offloaded in hardware
所以利用 RDMA 技術(shù)進行數(shù)據(jù)傳輸看起來像下面一樣:

從上面看出,使用了 RDMA 技術(shù)之后,雖然源端主機和目標主機是跨網(wǎng)絡(luò)的,但是他們之間的數(shù)據(jù)交互是直接從對方內(nèi)存獲取的,這明顯會加快整個計算過程。
好,現(xiàn)在基礎(chǔ)的知識咱們已經(jīng)獲取到了,我們正式進入本文主題。由 Mellanox Technologies 公司開發(fā)并開源的 SparkRDMA ShuffleManager (GitHub 地址:https://github.com/Mellanox/SparkRDMA)就是采用 RDMA 技術(shù),使得 Spark 作業(yè)在 Shuffle 數(shù)據(jù)的時候使用 RDMA 方式,而非標準的 TCP 方式。在 SparkRDMA 的官方 Wiki 里面有如下介紹:
SparkRDMA is a high-performance, scalable and efficient ShuffleManager plugin for Apache Spark. It utilizes RDMA (Remote Direct Memory Access) technology to reduce CPU cycles needed for Shuffle data transfers. It reduces memory usage by reusing memory for transfers instead of copying data multiple times down the traditional TCP-stack.
可以看出,SparkRDMA 就是擴展了 Spark 的 ShuffleManager 接口,并且采用了 RDMA 技術(shù)。在測試的結(jié)果顯示,采用 RDMA 進行 Shuffle 數(shù)據(jù)比標準的方式快 2.18 倍!

SparkRDMA 開發(fā)者們給 Spark 社區(qū)提交了一個 Issue:[SPARK-22229] SPIP: RDMA Accelerated Shuffle Engine,詳細的設(shè)計文檔:這里。不過從社區(qū)的回復(fù)來看,最少目前不會整合到 Spark 代碼中去。
如果你想使用 SparkRDMA,我們需要 Apache Spark 2.0.0/2.1.0/2.2.0、Java 8 以及支持 RDMA 技術(shù)的網(wǎng)絡(luò)(比如:RoCE 和 Infiniband)。
SparkRDMA 官方為不同版本的 Spark 預(yù)先編譯好相應(yīng)的 jar 包,我們可以訪問 這里 下載。解壓之后會得到以下四個文件:
spark-rdma-1.0-for-spark-2.0.0-jar-with-dependencies.jar
spark-rdma-1.0-for-spark-2.1.0-jar-with-dependencies.jar
spark-rdma-1.0-for-spark-2.2.0-jar-with-dependencies.jar
libdisni.so
除了 libdisni.so 文件一定要安裝到 Spark 集群的所有節(jié)點上,其他的 jar 包只需要根據(jù)我們的 Spark 版本進行選擇。相關(guān)的文件部署好之后,我們需要將這個 SparkRDMA 模塊加入到 Spark 的運行環(huán)境中去,如下設(shè)置:
spark.driver.extraClassPath /path/to/SparkRDMA/spark-rdma-1.0-for-spark-2.0.0-jar-with-dependencies.jarspark.executor.extraClassPath /path/to/SparkRDMA/spark-rdma-1.0-for-spark-2.0.0-jar-with-dependencies.jar |
為了啟用 SparkRDMA Shuffle Manager 插件,我們還需要修改 spark.shuffle.manager 的值,只需要在 $SPARK_HOME/conf/spark-defaults.conf 里面加入以下的配合即可:
spark.shuffle.manager org.apache.spark.shuffle.rdma.RdmaShuffleManager |
其他的就和正常使用 Spark 一樣。
Copyright ? 2023 北京網(wǎng)瀚科技有限公司 版權(quán)所有京ICP備2023032204號-1 Xml網(wǎng)站地圖