作者:鄭锴,花名鐵傑,阿裡巴巴進階技術專家,Apache Hadoop PMC,Apache Kerby 創立者。深耕分布式系統開發和開源大資料多年,先後專注在安全,存儲和計算領域。之前在 Intel,目前轉戰阿裡雲上,緻力于提供更好用更有彈性的 Hadoop/Spark 大資料平台。
Spark 設計上的優秀無容置疑,甫一出道便搶了 Hadoop 的 C 位,在開源大資料的黃金十年裡一時風頭無兩,在人工智能時代的當下仍然能夠與時俱進,不可謂不牛逼。架構和設計上的卓越,不遑多言,美中不足之處自然也有不少,比如排程模型跟 MapReduce 這種計算範式過于耦合,Spark 最近引入 Barrier 排程模式就是為了支援深度學習這種新的計算類型,所幸在于對架構的改動不會傷經動骨。有些缺陷則不然,影響全局,調整起來絕非易事。這兒我主要想談下 Spark 的架構語言實作和多語言支援,談它的得與失,不過主要還是談問題談缺陷。
Spark 核心和架構建構在 Scala 上,對應用開發者也是言必稱 Scala,上來就秀代碼極簡的漂亮肌肉。在使用者接口上,從企業級應用的首選 Java,到資料科學家的 Python 和 R,再到商業智能 BI 的 SQL,官方都一一支援,按說已經很全面很完整了,各方神聖也都伺候到了,還有什麼抱怨的,言何缺陷?我們來看下目前存在的問題,希望不會變成雞蛋裡挑骨頭。首先,對 Python 的支援也就是 PySpark 複雜且效率低下,有點像 hack,十分像早期 Spark 攻城略地的産出。其實對 R 的支援 SparkR 也如出一轍,我們讨論清楚了 PySpark 也就明白了對其他語言的支援其實是類似的。從使用者的角度來看用 PySpark 寫程式的體驗還是很不錯的,跟 Scala 有點類似,簡潔而優雅,就跟寫個單機程式一樣,不需要考慮分布式處理的複雜性。然而在這件漂亮的外衣下,用 PySpark 寫的 Spark 程式就是比 Scala 版本慢,還動不動 OOM 掉。為什麼?我們來探一下究竟。一般 Spark 程式首先給定輸入也就是要處理的資料集,然後表達好針對這個資料集的每行記錄要處理的邏輯和轉換規則,再将結果列印出來或者儲存到檔案。背後 Spark 架構進行翻譯轉換,産出一個個 RDD 和這些 RDD 之間的關系,每個 RDD 表示對應的資料集和在該資料集上要執行的變換處理邏輯。這些 RDD 根據它們之間的依賴關系組成 DAG,對 DAG 翻譯轉換成 stages 和 tasks,這個過程在 driver 端由架構 Scala 代碼完成,包括對 stages 和 tasks 的排程執行;RDD 的處理邏輯對應使用者的 Scala 或 Python 代碼,因為要分布式并發處理,主要在 executor 上執行。是以,對于 Python 版本的 Spark 程式,在 driver 上和 executor 上都有要執行的 Python 代碼,必然需要對應的 Python 解釋器來執行;然而 Spark 計算架構是 Scala/Java 代碼實作的,driver 和 executor 整體上得跑在 JVM 程序裡面。那麼如何在 driver 端和 executor 上同時執行代表使用者邏輯的 Python 代碼和核心引擎的 JVM 代碼,并在兩者之間進行互動和協調呢?PySpark 的做法是在 driver 端和 executor 上伴随必需的 JVM 程序,再 launch 起來單獨的 Python 解釋執行程序,然後通過 socket,檔案和 pipeline 進行互動和協作。這不能不說是個非常低效的做法,因為 Spark 程式通常而言并非一個普通的應用,要處理非常大的資料集。對于成千上萬行記錄的處理,都要在 executor 上通過跨程序管道到 Python 程序上來回一趟,末了在 driver 上為了傳遞計算結果可能還要寫個磁盤檔案才能轉給 Python 程序,為此涉及到大量記錄資料在 Python 和 Java 之間要序列化和反序列化,效率可想而知。開啟新的 Python 程序直接執行使用者的代碼省事倒是省事,除了效率問題,考慮到程序管理,記憶體控制,容器環境和資料安全,這樣做的代價還是很大的,然而 Spark 卻不得不這樣做,主要是因為受限于它在語言支援上面缺乏長遠的考慮和整體的設計,這就是我想講的最重要的問題。
在語言支援上,從一開始 Spark 的關注點就是“糖衣”而非“炮彈”,在使用者體驗上追求資料處理邏輯表達的簡潔有力,是以完勝當時的各種計算架構而後一騎絕塵。記得在 Hadoop 如日中天的時候,筆者所在的 Intel 大資料團隊正在玩 Hadoop 不亦樂乎,Spark 的作者 Matei 先生在遠端會議上向我們示範當時還十分稚嫩的 Spark,看到那個有名的 MapReduce Helloworld 例子 WordCount 程式隻需要兩三行 Scala 代碼搞定,真是駭人。Spark 能夠在短時間内搶了 Hadoop 的風頭,除了性能更快,毫無疑問這也是個關鍵因素。然而這種簡潔有力,在多大程度上要歸功于 Scala,其實不太好講。感覺最本質的還是在于函數式語言的支援, RDD 本身的抽象,豐富的算子支援和巧妙的關系推導,這部分可以歸為引擎層面,大體上用其他語言,比如更擅長做系統架構的,C++,應該也能實作得出來。至于使用者的程式是用 Scala 還是 Python,隻要支援 closures,應該都能行,簡潔程度上不會差别太大,也完全可以多支援一些語言,每個使用者具體用哪一個要看個人的偏好,沒有道理讓大家都去學一個新的語言。可惜的是,Spark 引擎的實作應該是受到了主要使用者接口語言 Scala 的影響,也采用了 Scala,部分采用 Java,但本質上都是 JVM 語言,這樣做的好處是一鍋煮,省事。考古學家可以列出一大堆使用 Scala 的好處,比如代碼行數少,codegen 給力之類的,但是這些都是局部的,從整體上 Spark 作為一個統一的大資料處理平台,其實更需要長遠的通盤考慮。這個考慮就是在使用者接口上要能夠更快更好地支援更多的使用者語言,在計算引擎上能夠支援硬體層面的極緻性能優化,在計算場景上也能支援其他計算引擎的內建。
這個考慮簡單來說就是缺乏對架構層面的 C/C++ 支援。當然這個支援很難在第一天就考慮進來,畢竟關注點不在這兒,那個時候估計 Matei 先生也想不到 Spark 會這麼成功。然而架構層面缺乏對 C/C++ 的原生支援或者換句話說,架構核心沒有采用 C/C++ 這種 native 語言來開發,其弊端和對 Spark 今後長遠發展的影響毫無疑問顯而易見。C/C++ 作為系統語言,下可以跟硬體直接打交道,上可以直接對接各種開發語言,是以也不難支援各種計算處理庫和引擎。Spark 本身定位為一個大資料處理平台,如果核心公共邏輯和操作交給 C/C++ 來實作,那麼首先支援 Python 這種使用者接口語言,直接利用 FFI 機制調用就是了,簡單且無損效率。主流的開發語言基本上都很好地支援 C/C++,Python 不說,像 Java,Go,Rust,Julia,都是。Spark 添加一個新的語言支援,就簡化為添加一個新的 binding,還好維護,也不用擔心這個功能被閹割,那個支援還不全。對新的硬體做優化也不成問題,比如從計算新貴 GPU 到 RDMA,再到可持久化大記憶體 AEP,根本不會受限于 JVM 的限制,各大硬體廠商都能自己撸起袖子開搞,Spark 坐享其成就是。現在對這些新硬體的支援為什麼上不了,社群不接受?個人認為主要還是缺乏架構層面的支援,搞出來的都像是 hack,進去也是麻煩。看看人家 Tensorflow 就知道了,CPU,TPU,GPU 都能玩得轉。核心架構采用 Scala/Java 來實作,還有一個重要的影響是資料集的記憶體表示,早期 Spark 直接用 Java 對象來表示資料記錄,需要持久化或者網絡傳輸要序列化和反序列化,當然在這一點上 Spark 後來很快意識到了問題,通過 offheap 和 Tunsten 項目馬上把問題解了,所幸還有招數。如果是 C/C++ 實作的,資料的記憶體布局必然會采取類似 Arrow 的這種中性表示,友善各種使用者接口語言來通路和操作,就像深度學習架構裡面常見的 tensor,必須考慮高效傳遞。最後一點,采用 Scala/Java 來實作的 Spark 架構,雖然整合開源大資料領域和企業級應用裡面很常見的各種資料源得心應手,但要整合內建更多的計算架構則就力不從心了。類似于對新硬體的支援,看一下 Yahoo 對 Caffe 和 Tensorflow 的支援就明白了,隻能 hack 一下自己玩,不可能融入到 Spark 裡面流行起來,要原生支援 deep learning,像 machine learning,可以,但要自己撸。Spark 自己花了很大力氣搞 mllib,Intel 搞 BigDL,都是沒辦法,因為缺乏核心架構的給力支援,不能直接把這些領域裡面現成的庫實作和計算引擎內建進來。如果核心架構是是 C/C++ 實作的,內建 PyTorch 和 Tensorflow 能有多大的問題?無非是多挂一個動态子產品或搞一個擴充插件的事情。
好吧,啰嗦到這兒,問題有解嗎?肯定有。Spark 搞定了使用者生态,隻要保持接口相容不變,核心架構來個天翻地覆,改弦更張換個語言來實作,未嘗不可,就看有沒有人願意這麼幹。有沒有更取巧的辦法呢,不用聽起來這麼吓人?答案也是肯定的,筆者所在的團隊就在幹這樣的事情,不過我們可以下次再行文讨論,有興趣的同學可以聯系我們,也歡迎加入,一起做出來,擁抱這個人工智能時代。對了,我們是阿裡巴巴計算平台,開源大資料部門 EMR,緻力于在雲上打造極緻的彈性 Spark 計算體驗,做會在雲上玩的 Spark,歡迎了解。技術方案和細節,我們可以下次再行文讨論,有興趣的同學可以聯系我,本人郵箱zhengkai.zkATalibaba-inc.com,也歡迎加入釘釘群 Apache Spark 中國技術交流群,群号 23109202;阿裡雲 E-MapReduce 技術交流群,群号21784001。或者掃碼加入:
