豆瓣成立于 2005 年,是中國最早的社交網(wǎng)站之一。在 2009 到 2019 的十年間,豆瓣數(shù)據(jù)平臺經(jīng)歷了幾輪變遷,形成了 DPark + Mesos + MooseFS 的架構(gòu)。
由機(jī)房全面上云的過程中,原有這套架構(gòu)并不能很好的利用云的特性,豆瓣需要做一次全面的重新選型,既要考慮未來十年的發(fā)展趨勢,也需要找到與現(xiàn)有組件兼容且平滑過渡的解決方案。一番改造后, 豆瓣數(shù)據(jù)平臺目前形成了 Spark + Kubernetes + JuiceFS 的云上數(shù)據(jù)湖架構(gòu),本文將分享此次選型升級的整體歷程。
01 豆瓣早期數(shù)據(jù)平臺
在 2019 年,豆瓣所使用的數(shù)據(jù)平臺主要由以下組件構(gòu)成:
Gentoo Linux,內(nèi)部使用的 Linux 發(fā)行版;MooseFS ,分布式文件系統(tǒng);Apache Mesos 負(fù)責(zé)整個(gè)集群的資源管理,以及 Dpark 作為分布式計(jì)算框架提供給開發(fā)者使用。
(豆瓣早期數(shù)據(jù)平臺架構(gòu))
從上圖可以看到在這個(gè)數(shù)據(jù)平臺中,計(jì)算和存儲是一體的,每個(gè)計(jì)算任務(wù)是由 Mesos 進(jìn)行調(diào)度的。計(jì)算任務(wù)的 I/O 操作都是通過 MooseFS 的 Master 獲取元數(shù)據(jù),并在本地獲取需要計(jì)算的數(shù)據(jù)。此外,GPU 計(jì)算集群也是通過 Mesos 進(jìn)行管理,不同的是, GPU 會基于顯存進(jìn)行共享。
平臺組件介紹
Gentoo Linux
Gentoo Linux 是一個(gè)較為小眾的 Linux 發(fā)行版,具有幾乎無限制的適應(yīng)性特性,是一個(gè)原發(fā)行版。Gentoo Linux 采用滾動更新的方式,所有軟件包都直接從社區(qū)中獲取二進(jìn)制包,我們則通過源代碼構(gòu)建我們所需的軟件包。Gentoo Linux 有一個(gè)強(qiáng)大的包管理器,使用它也會帶來很多便利,也同時(shí)存在一些問題。比如,滾動更新的速度非常快,但對于服務(wù)器來說,可能存在一定的不穩(wěn)定性。
使用源代碼構(gòu)建軟件包的好處是當(dāng)社區(qū)沒有預(yù)編譯好我們所需的軟件包時(shí),我們可以非常簡單地構(gòu)建出自己所需的軟件包,并且當(dāng)已有的軟件包無法滿足我們的需求時(shí),也可以很容易地進(jìn)行定制調(diào)整。但這也會帶來較高的維護(hù)成本。
另外,如果所有軟件包都能按照規(guī)范進(jìn)行編寫的話,依賴沖突問題幾乎是不存在的,因?yàn)樵诖虬^程中就已經(jīng)可以發(fā)現(xiàn)。但實(shí)際情況是并不是所有軟件包都能遵守一個(gè)好的依賴描述的約定,因此依賴沖突問題可能仍然存在。
Gentoo Linux 是較為小眾的選擇,盡管社區(qū)質(zhì)量很高,但是用戶也比較少,一些新項(xiàng)目可能沒有用戶進(jìn)行足夠的測試,我們在實(shí)際使用過程中會遇到各種各樣的問題。這些問題大部分需要我們自己解決,如果等待其他人回復(fù)的話,響應(yīng)會比較慢。
MooseFS
MooseFS 是一個(gè)開源的、符合 POSIX 標(biāo)準(zhǔn)的分布式文件系統(tǒng),它只使用 FUSE 作為 I/O 接口,并擁有分布式文件系統(tǒng)的標(biāo)準(zhǔn)特性,如容錯(cuò)、高可用、高性能和可擴(kuò)展性。
對于幾乎所有需要使用標(biāo)準(zhǔn)文件系統(tǒng)的場景,我們都使用 MooseFS 作為替代品,并在其基礎(chǔ)上開發(fā)了一些自己的小工具。例如,我們可以直接使用分布式文件系統(tǒng)來處理 CDN 的回源。在早期版本中,MooseFS 沒有主節(jié)點(diǎn)的備份功能,因此我們開發(fā)了一個(gè) ShadowMaster 作為元數(shù)據(jù)的熱備節(jié)點(diǎn),并編寫了一些分析 MooseFS 元數(shù)據(jù)的工具,以解決一些運(yùn)維問題。作為一個(gè)存儲設(shè)施,MooseFS 整體比較穩(wěn)定,并且沒有出現(xiàn)重大的問題。
Apache Mesos
Mesos 是一個(gè)開源的集群管理器,與YARN 有所不同,它提供公平分配資源的框架,并支持資源隔離,例如 CPU 或內(nèi)存。Mesos 早在 2010 年就被 Twitter 采用, IBM 在 2013 年開始使用。
Dpark
由于公司全員使用 Python,因此使用了 Python 版的 Spark,即 Dpark,它擴(kuò)展了RDD API,并提供了 DStream。
公司內(nèi)部還開發(fā)了一些小工具,例如 drun 和 mrun,可以通過 Dpark 將任意 Bash 腳本或數(shù)據(jù)任務(wù)提交到 Mesos 集群,并支持 MPI 相關(guān)的任務(wù)提交。Dgrep 是用于快速查詢?nèi)罩镜男」ぞ撸琂uiceFS 也提供了類似的工具。雖然 Dpark 本身可以容器化,但公司主要的數(shù)據(jù)任務(wù)是在物理服務(wù)器上運(yùn)行的。支持容器化可以讓場內(nèi)任務(wù)更好地利用線上業(yè)務(wù)的模型代碼。
02 平臺演進(jìn)的思考
在 2019 年,公司決定將基礎(chǔ)設(shè)施轉(zhuǎn)移到云端并實(shí)現(xiàn)計(jì)算和存儲分離,以提高平臺的靈活性。由于以前的計(jì)算任務(wù)在物理機(jī)上運(yùn)行,隨著時(shí)間的推移,出現(xiàn)了越來越多的依賴沖突問題,維護(hù)難度不斷增加。
同時(shí),公司希望內(nèi)部平臺能夠與當(dāng)前的大數(shù)據(jù)生態(tài)系統(tǒng)進(jìn)行交互,而不僅僅是處理文本日志或無結(jié)構(gòu)化、半結(jié)構(gòu)化的數(shù)據(jù)。此外,公司還希望提高數(shù)據(jù)查詢效率,現(xiàn)有平臺上存儲的數(shù)據(jù)都是行存儲,查詢效率很低。最終,公司決定重新設(shè)計(jì)一個(gè)平臺來解決這些問題。
平臺演進(jìn)時(shí),我們沒有非常強(qiáng)的兼容性需求。只要成本收益合理,我們就可以考慮將整個(gè)平臺替換掉。這就像是環(huán)法自行車比賽中,如果車有問題就會考慮換車,而不是只換輪子。在更換平臺時(shí),我們?nèi)绻l(fā)現(xiàn)現(xiàn)有平臺的任務(wù)無法直接替換,可以先保留它們。在切換過程中,我們有以下主要需求:
? Python 是最優(yōu)先考慮的開發(fā)語言。
?必須保留 FUSE 接口,不能直接切換到 HDFS 或者 S3。
?盡可能統(tǒng)一基礎(chǔ)設(shè)施,已經(jīng)選用了部分 Kubernetes,就放棄了 Mesos 或其他備選項(xiàng)。
?新平臺的學(xué)習(xí)成本應(yīng)盡可能低,讓數(shù)據(jù)組和算法組的同事能夠以最低的成本切換到新的計(jì)算平臺上。
03 云上構(gòu)建數(shù)據(jù)平臺
目前的云上數(shù)據(jù)平臺幾乎是全部替換了,Gentoo Linux 的開發(fā)環(huán)境變成了 Debian based container 的環(huán)境, MooseFS 是換用了現(xiàn)在的 JuiceFS,資源管理使用了 Kubernetrs,計(jì)算任務(wù)的開發(fā)框架使用了 Spark,整體進(jìn)行了徹底替換的,其他的設(shè)施是在逐漸縮容的過程,還會共存一段時(shí)間。
(豆瓣數(shù)據(jù)平臺架構(gòu))
JuiceFS 作為統(tǒng)一存儲數(shù)據(jù)平臺
為了更好地滿足不同的 I/O 需求和安全性考慮,我們會為不同的使用場景創(chuàng)建不同的 JuiceFS 卷,并進(jìn)行不同的配置。JuiceFS 相對于之前的 MooseFS,創(chuàng)建文件系統(tǒng)更加簡單,實(shí)現(xiàn)了按需創(chuàng)建。除了 SQL 數(shù)據(jù)平臺外,我們的使用場景基本上都是由 JuiceFS 提供的服務(wù)。
在 JuiceFS 中,數(shù)據(jù)有幾種類型:在線讀寫、在線讀取離線寫入、在線寫入離線讀取、離線讀寫。
所有的讀寫類型都在 JuiceFS 上進(jìn)行,比如日志匯聚到卷中,Spark 可能會讀取并進(jìn)行 ETL,然后將數(shù)據(jù)寫入數(shù)據(jù)湖。此外,從 Kafka 數(shù)據(jù)源讀取的數(shù)據(jù)也會通過 Spark 進(jìn)行處理并寫入數(shù)據(jù)湖。
Spark 的 Check Point 直接存儲在另一個(gè) JuiceFS 卷中,而數(shù)據(jù)湖的數(shù)據(jù)則直接提供給算法組的同學(xué)進(jìn)行模型訓(xùn)練,并將訓(xùn)練結(jié)果通過 JuiceFS 寫回。我們的運(yùn)維團(tuán)隊(duì)則通過各種腳本或工具來管理 JuiceFS 上的文件生命周期,包括是否對其進(jìn)行歸檔處理等。因此,整個(gè)數(shù)據(jù)在 JuiceFS 中的流轉(zhuǎn)過程大致如上圖所示。
新數(shù)據(jù)平臺組件介紹
Debian based container
首先,運(yùn)維團(tuán)隊(duì)選擇了 Debian based container 作為基礎(chǔ)鏡像,我們就直接使用了。我們的計(jì)算平臺的鏡像很大,為了解決任務(wù)啟動速度的問題,團(tuán)隊(duì)在每個(gè)節(jié)點(diǎn)上預(yù)拉取了鏡像。
JuiceFS
切換到 JuiceFS 存儲系統(tǒng)時(shí),用戶感受不到變化,JuiceFS 非常穩(wěn)定。JuiceFS 比 MooseFS 更好的一點(diǎn)是,它擁有 HDFS 的 SDK,方便了團(tuán)隊(duì)將來切換到 Spark 等工具。團(tuán)隊(duì)在 Kubernetes 上使用了 JuiceFS CSI,可以直接使用 JuiceFS 作為 Persist Volume,用起來十分方便。JuiceFS 團(tuán)隊(duì)溝通高效,解決問題迅速。例如,當(dāng) stream 的 checkpoint 頻率太高時(shí),JuiceFS 團(tuán)隊(duì)早早通知并迅速解決。
Kubernentes
我們早在 1.10 版本的時(shí)候就開始試用 Kubernetes。后來豆瓣對外的服務(wù)集群在 1.12 版本開始逐步遷移到 Kubernetes,基本上是在現(xiàn)有機(jī)器上完成了原地的替換。計(jì)算集群則是在上云后開始搭建的,基于1.14 版本。我們在版本升級方面可能比其他公司更為激進(jìn),目前我們的 Kubernetes 版本已經(jīng)升級到了1.26 版。
我們選擇 Kubernetes 作為計(jì)算平臺的原因之一是它有比較統(tǒng)一的組件。此外,通過 scheduling framework 或者 Volcano,我們可以影響它的調(diào)度,這是我們比較希望擁有的一個(gè)特性。
我們還可以利用社區(qū)的 Helm 非常快速地部署一些需要的東西,比如 Airflow、Datahub 和 Milvus 等服務(wù),這些服務(wù)都是通過 Helm 部署到我們的離線 Kubernetes 集群中提供的。
Spark
在最開始測試 Spark 時(shí),我們像使用 Dpark 一樣將任務(wù)運(yùn)行在 Mesos 集群上。之后我們選定了 Kubernetes,使用 Google Cloud Platform 上的 spark-on-k8s-operator 將 Spark 任務(wù)部署到 Kubernetes 集群中,并部署了兩個(gè) Streaming 任務(wù),但并未進(jìn)行大規(guī)模的部署。
隨后,我們確定了使用 Kubernetes 和 Airflow,計(jì)劃自己實(shí)現(xiàn)一個(gè) Airflow Operator,在 Kubernetes 中直接提交 Spark 任務(wù),并使用 Spark 的 Cluster Mode 將任務(wù)提交到 Kubernetes 集群中。
對于開發(fā)環(huán)境,我們使用 JupyterLab 進(jìn)行開發(fā)。廠內(nèi)有一個(gè) Python 庫對 Spark Session 進(jìn)行了一些小的預(yù)定義配置,以確保 Spark 任務(wù)能夠直接提交到 Kubernetes 集群上。
目前,我們使用 Kubernetes Deployment 直接部署 Streaming 任務(wù),這是一個(gè)很簡單的狀態(tài),未來可能會有一些改進(jìn)的地方。另外,我們正在準(zhǔn)備試用 Kyuubi & Spark Connect 項(xiàng)目,希望能夠?yàn)榫€上任務(wù)提供更好的讀寫離線數(shù)據(jù)的體驗(yàn)。
我們的版本升級非常激進(jìn),但確實(shí)從社區(qū)中獲益匪淺。我們解決了日常計(jì)算任務(wù)中許多常見的優(yōu)化場景。我們激進(jìn)升級的原因是希望能夠盡可能多地利用社區(qū)的資源,提供新特性給開發(fā)者。但我們也遇到了問題,例如 Spark 3.2 的 parquet zstd 壓縮存在內(nèi)存泄漏。為了規(guī)避這個(gè)問題,我們提前引入了未發(fā)布的補(bǔ)丁。
現(xiàn)在,我們使用兩種方式來讀寫 JuiceFS 數(shù)據(jù):FUSE 和 HDFS。FUSE 主要用于 ETL 任務(wù),例如讀寫日志和 CSV 文件。我們也會將 Hive 表轉(zhuǎn)存為 CSV 文件下載供未切換到 Spark 的任務(wù)進(jìn)行計(jì)算。其他的數(shù)據(jù),則直接通過預(yù)先配置好的 HDFS(如 Hive Table 和 Iceberg Table)進(jìn)行讀寫,這大大簡化了我們的工作。
在數(shù)據(jù)湖的選擇上,我們一開始考慮了 Delta Lake,但由于它不支持 Merge on Read,在目前的使用場景存在寫放大,我們放棄了它。取而代之,我們選擇了 Iceberg,并將其用于 MySQL CDC 處理。我們將數(shù)據(jù)直接存儲在 JuiceFS 上進(jìn)行讀寫,并且目前沒有遇到任何性能上的問題。未來,如果我們需要擴(kuò)大規(guī)模使用,可能需要與 JuiceFS 的團(tuán)隊(duì)溝通一下,看看有哪些優(yōu)化措施。
04 收獲與展望
我們切換到新的計(jì)算平臺之后,獲得了很多原來沒有的功能。例如,我們現(xiàn)在可以使用基于 SQL 的大量任務(wù),這些任務(wù)的性能比以前好得多,各種報(bào)表的實(shí)時(shí)性也更好了。
與 Mesos 的情況不同,Spark 聲明了多少資源就使用多少資源,這與以前的 Dpark 相比有很大的差異,因?yàn)橐郧按蠹叶际枪椒窒恚嗷ブg會有影響。現(xiàn)在,每個(gè)任務(wù)的執(zhí)行時(shí)間都比較可預(yù)測,任務(wù)評估也比較容易預(yù)測,整個(gè)新平臺對于業(yè)務(wù)數(shù)據(jù)的讀取也有更好的時(shí)效性。
以前的歷史包袱是相當(dāng)沉重的,現(xiàn)在我們已經(jīng)趕上了社區(qū)的步伐。去年年末的各種統(tǒng)計(jì)和排名都已經(jīng)遷移到了新的計(jì)算平臺上,并且運(yùn)行非常穩(wěn)定。
我們正在優(yōu)先考慮采取一些成本下降措施,以實(shí)現(xiàn)整個(gè)計(jì)算集群的動態(tài)擴(kuò)縮容。我們正積極努力實(shí)現(xiàn)此目標(biāo),并希望提供更加穩(wěn)定的 SQL 接口。為此,我們計(jì)劃采用支持 Multi-tenant 的 SQL 服務(wù)器,并嘗試引入 Spark 3.4 的最新特性。
長遠(yuǎn)來看,我們希望通過 Spark Remote Shuffle Service 進(jìn)一步實(shí)現(xiàn)存算分離,以便更有效地利用資源。也許未來我們會開發(fā)一個(gè)“Spark as a Service”,提供給開發(fā)者使用。總之,我們正在追趕社區(qū)的步伐,并不斷努力提升我們的技術(shù)水平。
-
數(shù)據(jù)存儲
+關(guān)注
關(guān)注
5文章
977瀏覽量
50974 -
SQL
+關(guān)注
關(guān)注
1文章
770瀏覽量
44190 -
分布式
+關(guān)注
關(guān)注
1文章
913瀏覽量
74568
原文標(biāo)題:從本地到云端:豆瓣如何使用JuiceFS實(shí)現(xiàn)統(tǒng)一的數(shù)據(jù)存儲
文章出處:【微信號:OSC開源社區(qū),微信公眾號:OSC開源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論