今天的案例分享來自社區(qū)用戶一面數(shù)據(jù),這是一家通過解讀電商平臺(tái)和社交媒體渠道的海量數(shù)據(jù),為全球快消巨頭(如寶潔、聯(lián)合利華和瑪氏等)提供實(shí)時(shí)、全面的數(shù)據(jù)洞察的公司。
在去年的案例中,一面分享了架構(gòu)設(shè)計(jì)和實(shí)踐。本次案例,進(jìn)一步補(bǔ)充了在后續(xù)數(shù)據(jù)遷移過程中一面遇到的具體挑戰(zhàn)以及分級(jí)存儲(chǔ)的實(shí)踐。如果你正在考慮將 Hadoop 遷移到云上,這篇文章從架構(gòu)設(shè)計(jì)到實(shí)際操作都涵蓋了豐富的內(nèi)容,是一篇不容錯(cuò)過的案例。
一面數(shù)據(jù)原有的技術(shù)架構(gòu)是在線下機(jī)房中使用 CDH 構(gòu)建的大數(shù)據(jù)集群。自公司成立以來,每年都保持著高速增長,業(yè)務(wù)的增長帶來了數(shù)據(jù)量的劇增。
在過去幾年中,我們按照每 1 到 2 年的規(guī)劃擴(kuò)容硬件,但往往在半年之后就不得不再次擴(kuò)容。而每次擴(kuò)容都需要花費(fèi)大量精力。
為了解決包括擴(kuò)容周期長、計(jì)算存儲(chǔ)資源不匹配以及高昂的運(yùn)維成本等這些問題,我們決定對數(shù)據(jù)架構(gòu)進(jìn)行改造,并將數(shù)據(jù)遷移到云端,采用存算分離的結(jié)構(gòu)。 在這個(gè)案例中,我們將為大家介紹 Hadoop 上云的架構(gòu)設(shè)計(jì)、選型的思考、組件評(píng)估以及數(shù)據(jù)遷移的整個(gè)過程。
目前,基于 JuiceFS 我們實(shí)現(xiàn)了計(jì)算和存儲(chǔ)分離的架構(gòu),總存儲(chǔ)量增加了 2 倍;性能方面的變化無明顯感知,運(yùn)維成本大幅降低。在案例的末尾還附上了針對阿里云 EMR 以及 JuiceFS 的一手運(yùn)維經(jīng)驗(yàn),希望這個(gè)案例能為其他面臨類似問題的同行提供有價(jià)值的參考。
舊架構(gòu)及挑戰(zhàn)
為了滿足業(yè)務(wù)需求,一面數(shù)據(jù)抓取了國內(nèi)外數(shù)百個(gè)大型網(wǎng)站的數(shù)據(jù),目前數(shù)量已經(jīng)超過 500 個(gè),并積累了大量的原始數(shù)據(jù)、中間數(shù)據(jù)和結(jié)果數(shù)據(jù)。隨著我們不斷增加抓取的網(wǎng)站數(shù)量和服務(wù)的客戶群,數(shù)據(jù)量也在快速增長。因此,我們著手開始進(jìn)行擴(kuò)容以滿足需求的增長。
原有的架構(gòu)是在一個(gè)線下機(jī)房使用 CDH 構(gòu)建了一個(gè)大數(shù)據(jù)集群。如下圖所示,我們主要使用了 Hive、Spark 和 HDFS 等組件。在 CDH 的上游有多種數(shù)據(jù)生產(chǎn)系統(tǒng),在這里只列出了 Kafka,因?yàn)榕c JuiceFS 相關(guān);除了 Kafka 之外,還有其他一些存儲(chǔ)方式,包括 TiDB、HBase、MySQL 等等。
一面數(shù)據(jù)原有數(shù)據(jù)架構(gòu)
數(shù)據(jù)流向方面,我們有一個(gè)上游的業(yè)務(wù)系統(tǒng)和數(shù)據(jù)采集系統(tǒng),數(shù)據(jù)會(huì)被采集下來后寫入 Kafka。然后我們使用一個(gè) Kafka Connect 集群,將數(shù)據(jù)同步到 HDFS。
在這個(gè)架構(gòu)上方,我們使用了一個(gè)自研的數(shù)據(jù)開發(fā)平臺(tái),稱為 OneWork,用于開發(fā)和管理各種任務(wù)。這些任務(wù)會(huì)通過 Airflow 下發(fā)到任務(wù)隊(duì)列進(jìn)行調(diào)度。
挑戰(zhàn)
業(yè)務(wù) / 數(shù)據(jù)會(huì)增長比較快,業(yè)務(wù)擴(kuò)容周期長。公司在 2016 年線下機(jī)房部署了 CDH 集群,到 2021 年已存儲(chǔ)和處理 PB 級(jí)的數(shù)據(jù)。公司自創(chuàng)立以來一直保持每年翻一番的高增長,而比業(yè)務(wù)量增長更快的是 Hadoop 集群的數(shù)據(jù)量。
在這幾年間,按 1 到 2 年規(guī)劃的硬件,往往因數(shù)據(jù)增長超出預(yù)期而在半年后不得不再次擴(kuò)容。每次擴(kuò)容周期可達(dá)到一個(gè)月,除了花費(fèi)大量精力跟進(jìn)行政和技術(shù)流程,業(yè)務(wù)端也不得不安排較多人日控制數(shù)據(jù)量。如果選擇購買硬盤和服務(wù)器來進(jìn)行擴(kuò)容,實(shí)施周期會(huì)相對較長。
存儲(chǔ)計(jì)算耦合,容量規(guī)劃難,容易錯(cuò)配。 傳統(tǒng)的 Hadoop 架構(gòu)中,存儲(chǔ)和計(jì)算是緊密耦合的,難以根據(jù)存儲(chǔ)或計(jì)算的需求獨(dú)立進(jìn)行擴(kuò)容和規(guī)劃。舉個(gè)例子,假設(shè)我們需要擴(kuò)容存儲(chǔ),于是首先需要購買一批新的硬盤,同時(shí)連帶著需要購買計(jì)算資源。在最初時(shí),計(jì)算資源可能會(huì)變得過剩,因?yàn)榭赡軐?shí)際不需要那么多的計(jì)算資源,從而一定程度上導(dǎo)致了超前投資。
CDH 版本比較老,不敢升級(jí)。 我們因?yàn)榧阂步ǖ谋容^早了,為了穩(wěn)定,也就不敢升級(jí)了。
運(yùn)維成本較高(全公司僅 1 個(gè)全職運(yùn)維)公司當(dāng)時(shí)有 200 多個(gè)人,只有一個(gè)運(yùn)維,這意味著運(yùn)維工作的工作量很大。因此,我們希望能夠采用更穩(wěn)定、更簡單的架構(gòu)來提供支持。
機(jī)房存在單點(diǎn)風(fēng)險(xiǎn)??紤]到長遠(yuǎn)的因素,所有的數(shù)據(jù)都存儲(chǔ)在同一個(gè)機(jī)房中,這存在一定的風(fēng)險(xiǎn)。例如,如果光纜被挖斷,這種情況經(jīng)常發(fā)生,那么我們僅有一個(gè)機(jī)房仍然會(huì)面臨單點(diǎn)故障的風(fēng)險(xiǎn)。
新架構(gòu)與選型 選型考量
考慮到這些因素和挑戰(zhàn),我們決定進(jìn)行一些新的改變。以下是我們考慮架構(gòu)升級(jí)的一些主要維度:
上云,彈性伸縮,靈活運(yùn)維。利用云上的服務(wù)可以簡化運(yùn)維工作。例如,在存儲(chǔ)方面,盡管 HDFS 本身是一個(gè)穩(wěn)定且成熟的解決方案,但我們更愿意將時(shí)間投入到業(yè)務(wù)層面上,而不是底層的運(yùn)維工作。因此,使用云服務(wù)可能更加簡單。此外,通過利用云上的資源,我們可以實(shí)現(xiàn)彈性伸縮,無需等待長時(shí)間的硬件部署和系統(tǒng)配置周期。
存儲(chǔ)計(jì)算分離。我們希望將存儲(chǔ)和計(jì)算解耦,以實(shí)現(xiàn)更好的靈活性和性能。
盡量使用開源組件,避免云廠商綁定。盡管我們選擇上云,但我們不希望過于依賴云服務(wù)本身。我們在為客戶提供服務(wù)時(shí)會(huì)使用云原生的解決方案,例如使用 AWS Redshift 等,但我們在自身業(yè)務(wù)方面更傾向于使用開源組件。
盡可能與現(xiàn)有方案兼容,控制改動(dòng)成本和風(fēng)險(xiǎn)。我們希望新架構(gòu)與現(xiàn)有解決方案兼容,以避免引入額外的開發(fā)成本,并對我們的業(yè)務(wù)產(chǎn)生影響。
新架構(gòu):阿里云 EMR + OSS + JuiceFS
最終選擇的方案是使用“阿里云 EMR + JuiceFS + 阿里云 OSS” 來搭建存算分離的大數(shù)據(jù)平臺(tái),將云下數(shù)據(jù)中心的業(yè)務(wù)逐步遷移上云。
這個(gè)架構(gòu)使用對象存儲(chǔ)來替代 HDFS,并選擇了 JuiceFS 作為協(xié)議層,因?yàn)?JuiceFS 兼容 POSIX 和 HDFS 協(xié)議。在頂部,我們使用了云上半托管的 Hadoop 解決方案 EMR。它包含了很多 Hadoop 相關(guān)的組件,例如 Hive、Impala、Spark、Presto/Trino 等等。
一面數(shù)據(jù)架構(gòu)圖
阿里云 vs 其他公有云
首先是決定使用哪家云廠商。由于業(yè)務(wù)需求,AWS、Azure 和阿里云都有在用,綜合考慮后認(rèn)為阿里云最適合,有這些因素:
物理距離:阿里云在我們線下機(jī)房同城有可用區(qū),網(wǎng)絡(luò)專線的延遲小,成本低
開源組件齊全:阿里云 EMR 上包含的開源組件很多很全,除了我們重度使用的 Hive、Impala、Spark、Hue,也能方便集成 Presto、Hudi、Iceberg 等。我們在調(diào)研時(shí)發(fā)現(xiàn)只有阿里云 EMR 自帶了 Impala,AWS 和 Azure 要么版本低,要么要自己安裝部署。
JuiceFS vs JindoFS
阿里云的 EMR 本身也有使用 JindoFS 的存算分離方案,但基于以下考慮,我們最終選擇了 JuiceFS:
JuiceFS 使用 Redis 和對象存儲(chǔ)為底層存儲(chǔ),客戶端完全是無狀態(tài)的,可以在不同環(huán)境訪問同一個(gè)文件系統(tǒng),提高了方案的靈活性。而 JindoFS 元數(shù)據(jù)存儲(chǔ)在 EMR 集群的本地硬盤,不便于維護(hù)、升級(jí)和遷移。
JuiceFS 的存儲(chǔ)方案豐富,而且支持不同方案的在線遷移,提高了方案的可移植性。JindoFS 塊數(shù)據(jù)只支持 OSS.
JuiceFS 以開源社區(qū)為基礎(chǔ),支持所有公有云環(huán)境,方便后期擴(kuò)展到多云架構(gòu)。
關(guān)于 JuiceFS
直接截取官方文檔[1] 的介紹:
JuiceFS 是一款面向云原生設(shè)計(jì)的高性能共享文件系統(tǒng),在 Apache 2.0 開源協(xié)議下發(fā)布。提供完備的 POSIX[2] 兼容性,可將幾乎所有對象存儲(chǔ)接入本地作為海量本地磁盤使用,亦可同時(shí)在跨平臺(tái)、跨地區(qū)的不同主機(jī)上掛載讀寫。
JuiceFS 采用「數(shù)據(jù)」與「元數(shù)據(jù)」分離存儲(chǔ)的架構(gòu),從而實(shí)現(xiàn)文件系統(tǒng)的分布式設(shè)計(jì)。使用 JuiceFS 存儲(chǔ)數(shù)據(jù),數(shù)據(jù)本身會(huì)被持久化在對象存儲(chǔ)[3](例如,Amazon S3),相對應(yīng)的元數(shù)據(jù)可以按需持久化在 Redis、MySQL、TiKV、SQLite 等多種數(shù)據(jù)庫[4] 中。
除了 POSIX 之外,JuiceFS 完整兼容 HDFS SDK,與對象存儲(chǔ)結(jié)合使用可以完美替換 HDFS,實(shí)現(xiàn)存儲(chǔ)和計(jì)算分離。
JuiceFS 架構(gòu)圖
Hadoop 遷移云上 PoC 設(shè)計(jì)
PoC 的目的是快速驗(yàn)證方案的可行性,有幾個(gè)具體目標(biāo):
驗(yàn)證 EMR + JuiceFS + OSS 整體方案的可行性
檢查 Hive、Impala、Spark、Ranger 等組件版本的兼容性
評(píng)估對比性能表現(xiàn),用了 TPC-DS 的測試用例和部分內(nèi)部真實(shí)業(yè)務(wù)場景,沒有非常精確的對比,但能滿足業(yè)務(wù)需求
評(píng)估生產(chǎn)環(huán)境所需的節(jié)點(diǎn)實(shí)例類型和數(shù)量(算成本)
探索數(shù)據(jù)同步方案
探索驗(yàn)證集群與自研 ETL 平臺(tái)、Kafka Connect 等的集成方案
期間做了大量測試、文檔調(diào)研、內(nèi)外部(阿里云 + JuiceFS 團(tuán)隊(duì))討論、源碼理解、工具適配等工作,最終決定繼續(xù)推進(jìn)。
實(shí)施
我們在 2021 年 10 月開始探索 Hadoop 的上云方案;11 月做了大量調(diào)研和討論,基本確定方案內(nèi)容;12 月和 2022 年 1 月春節(jié)前做了 PoC 測試,在春節(jié)后 3 月份開始搭建正式環(huán)境并安排遷移。為了避免導(dǎo)致業(yè)務(wù)中斷,整個(gè)遷移過程以相對較慢的節(jié)奏分階段執(zhí)行, 遷移完后,云上的 EMR 集群數(shù)據(jù)量預(yù)計(jì)會(huì)超過單副本 1 PB。
整體架構(gòu)設(shè)計(jì)
做完技術(shù)選型之后,架構(gòu)設(shè)計(jì)也能很快確定下來??紤]到除了 部分業(yè)務(wù)仍然會(huì)保留在數(shù)據(jù)中心的 Hadoop 集群,所以整體實(shí)際上是個(gè)混合云的架構(gòu)。
整體架構(gòu)大致如上圖所示:左側(cè)是的線下機(jī)房,使用了傳統(tǒng)的 CDH 架構(gòu)和一些 Kafka 集群。右側(cè)是部署在阿里云上的 EMR 集群。這兩部分通過一條高速專線進(jìn)行連接。頂部是 Airflow 和 OneWork,由于都支持支持分布式部署,因此可以輕松進(jìn)行水平擴(kuò)展。
數(shù)據(jù)遷移的挑戰(zhàn) 挑戰(zhàn) 1:Hadoop 2 升到 Hadoop 3
我們 CDH 版本比較老,也不敢升級(jí),但我們既然做了遷移,肯定還是希望新集群能夠升級(jí)到新版本。在遷移過程中,需要注意 HDFS 2 和 3 之間的差異,接口協(xié)議和文件格式有可能會(huì)發(fā)生變化。JuiceFS 完美兼容 HDFS 2 & 3,很好地應(yīng)對了這個(gè)挑戰(zhàn)。
挑戰(zhàn) 2:Spark 2 升級(jí)到 Spark 3
Spark 的一個(gè)升級(jí)對我們影響是比較大的,因?yàn)橛胁簧俨患嫒莸母?。這就意味著原來在 Spark 2 上面寫的代碼需要完成修改才能適配到新的版本里面去。
挑戰(zhàn) 3:Hive on Spark 不支持 Spark 3
在機(jī)房環(huán)境中,默認(rèn)使用的是 CDH 自帶的 Hive on Spark,但當(dāng)時(shí) CDH 中的 Spark 版本只有 1.6。我們在云上使用的是 Spark 3,而 Hive on Spark 并不支持 Spark 3,這導(dǎo)致我們無法繼續(xù)使用 Hive on Spark 引擎。
經(jīng)過調(diào)研和測試,我們將 Hive on Spark 改為了 Hive on Tez。這個(gè)改動(dòng)相對來說還比較容易,因?yàn)?Hive 本身對于不同的計(jì)算引擎提供了抽象和適配,所以對于我們的上層代碼改動(dòng)較小。Hive on Tez 在性能上可能略慢于 Spark。此外,我們也關(guān)注國內(nèi)網(wǎng)易開源的一個(gè)新計(jì)算引擎 Kyuubi,它兼容 Hive,并提供了一些新特性。
挑戰(zhàn) 4:Hive 1 升級(jí)到 Hive 3,元數(shù)據(jù)結(jié)構(gòu)有變化
對于 Hive 升級(jí)來說,最主要的影響之一是元數(shù)據(jù)結(jié)構(gòu)的變化,因此在遷移過程中,我們需要進(jìn)行數(shù)據(jù)結(jié)構(gòu)的轉(zhuǎn)換。因?yàn)闊o法直接使用 Hive 來處理這種遷移,所以我們需要開發(fā)相應(yīng)的程序來進(jìn)行數(shù)據(jù)結(jié)構(gòu)的轉(zhuǎn)換。
挑戰(zhàn) 5:權(quán)限管理由 Sentry 替換為 Ranger
這是一個(gè)比較小的問題,就是我們之前使用 Sentry 做權(quán)限管理,這個(gè)社區(qū)不怎么活躍了,EMR 也沒有集成,所以就替換為 Ranger。
除了技術(shù)挑戰(zhàn)外,更大的挑戰(zhàn)來自與業(yè)務(wù)端。
業(yè)務(wù)挑戰(zhàn) 1:涉及的業(yè)務(wù)多,不能影響交付
我們擁有多個(gè)業(yè)務(wù),涉及不同的網(wǎng)站、客戶和項(xiàng)目。由于業(yè)務(wù)交付不能中斷,遷移過程必須進(jìn)行分業(yè)務(wù)處理,采用漸進(jìn)式遷移的方式。遷移過程中,數(shù)據(jù)的變動(dòng)會(huì)對公司的多個(gè)環(huán)節(jié)產(chǎn)生影響,例如 ETL 數(shù)據(jù)倉庫、數(shù)據(jù)分析師、測試和產(chǎn)品開發(fā)等。因此,我們需要進(jìn)行良好的溝通和協(xié)調(diào),制定項(xiàng)目管理計(jì)劃和排期。
業(yè)務(wù)挑戰(zhàn) 2:數(shù)據(jù)表、元數(shù)據(jù)、文件、代碼多
除了數(shù)據(jù),我們在上層還有許多業(yè)務(wù)代碼,包括數(shù)據(jù)倉庫的代碼、ETL 的代碼以及一些應(yīng)用程序的代碼,如 BI 應(yīng)用需要查詢這些數(shù)據(jù)。
數(shù)據(jù)遷移:存量文件 & 增量文件
要遷移的數(shù)據(jù)包括兩部分:Hive Metastore 元數(shù)據(jù)以及 HDFS 上的文件。由于不能中斷業(yè)務(wù),采用存量同步 + 增量同步(雙寫)的方式進(jìn)行遷移;數(shù)據(jù)同步完后需要進(jìn)行一致性校驗(yàn)。
存量同步
對于存量文件同步,可以使用 JuiceFS 提供的功能完整的數(shù)據(jù)同步工具 sync 子命令[5] 來實(shí)現(xiàn)高效遷移。JuiceFS sync 命令支持單節(jié)點(diǎn)和多機(jī)并發(fā)同步,實(shí)際使用時(shí)發(fā)現(xiàn)單節(jié)點(diǎn)開多線程即可打滿專線帶寬,CPU 和內(nèi)存占用低,性能表現(xiàn)非常不錯(cuò)。需要注意的是,同步過程中 sync 命令會(huì)在本地文件系統(tǒng)寫緩存,因此最好掛載到 SSD 盤來提升性能。
Hive Metastore 的數(shù)據(jù)同步則相對麻煩些:
兩個(gè) Hive 版本不一致,Metastore 的表結(jié)構(gòu)有差異,因此無法直接使用 MySQL 的導(dǎo)出導(dǎo)入功能
遷移后需要修改庫、表、分區(qū)存儲(chǔ)路徑(即 dbs 表的 DB_LOCATION_URI和 sds 表的 LOCATION)
因此我們開發(fā)了一套腳本工具,支持表和分區(qū)粒度的數(shù)據(jù)同步,使用起來很方便。
增量同步
增量數(shù)據(jù)主要來自兩個(gè)場景:Kafka Connect HDFS Sink 和 ETL 程序,我們采用了雙寫機(jī)制。
Kafka Connect 的 Sink 任務(wù)都復(fù)制一份即可,配置方式上文有介紹。ETL 任務(wù)統(tǒng)一在 OneWork 上開發(fā),底層使用 Airflow 進(jìn)行調(diào)度。通常只需要把相關(guān)的 DAG 復(fù)制一份,修改集群地址即可。實(shí)際遷移過程中,這一步遇到的問題最多,花了大量時(shí)間來解決。主要原因是 Spark、Impala、Hive 組件版本的差異導(dǎo)致任務(wù)出錯(cuò)或數(shù)據(jù)不一致,需要修改業(yè)務(wù)代碼。這些問題在 PoC 和早期的遷移中沒有覆蓋到,算是個(gè)教訓(xùn)。
數(shù)據(jù)校驗(yàn)
為了能讓業(yè)務(wù)放心的使用新的架構(gòu),數(shù)據(jù)校驗(yàn)必不可少。數(shù)據(jù)同步完后需要進(jìn)行一致性校驗(yàn),分三層:
文件一致。在存量同步階段做校驗(yàn),通常的方式是用 checksum. 最初的 JuiceFS sync 命令不支持 checksum 機(jī)制,我們建議和討論后,JuiceFS 團(tuán)隊(duì)很快就加上了該功能(issue,pull request[6])。除了 checksum,也可考慮使用文件屬性對比的方式:確保兩個(gè)文件系統(tǒng)里所有文件的數(shù)量、修改時(shí)間、屬性一致。比 checksum 的可靠性稍弱,但更輕量快捷。
元數(shù)據(jù)一致。有兩種思路:對比 Metastore 數(shù)據(jù)庫的數(shù)據(jù),或?qū)Ρ?Hive 的 DDL 命令的結(jié)果。
計(jì)算結(jié)果一致。即使用 Hive/Impala/Spark 跑一些查詢,對比兩邊的結(jié)果是否一致。一些可以參考的查詢:表 / 分區(qū)的行數(shù)、基于某個(gè)字段的排序結(jié)果、數(shù)值字段的最大 / 最小 / 平均值、業(yè)務(wù)中經(jīng)常使用的統(tǒng)計(jì)聚合等。
數(shù)據(jù)校驗(yàn)的功能也封裝到了腳本里,方便快速發(fā)現(xiàn)數(shù)據(jù)問題。
分級(jí)存儲(chǔ)
遷移完業(yè)務(wù)穩(wěn)定運(yùn)行后,我們開始考慮分級(jí)存儲(chǔ)。分級(jí)存儲(chǔ)在各種數(shù)據(jù)庫或存儲(chǔ)系統(tǒng)中都是一個(gè)常見問題,數(shù)據(jù)存在冷熱區(qū)別,而存儲(chǔ)介質(zhì)的價(jià)格也存在差異,因此我們希望將冷數(shù)據(jù)存儲(chǔ)在更便宜的存儲(chǔ)介質(zhì)上以控制成本。
在之前的 HDFS 中,我們已經(jīng)實(shí)施了分級(jí)存儲(chǔ)策略,購買了兩種類型的硬盤,將熱數(shù)據(jù)存儲(chǔ)在高速硬盤中,將冷數(shù)據(jù)存儲(chǔ)在低速硬盤中。
然而,JuiceFS 為了優(yōu)化性能采取的數(shù)據(jù)分塊模式,會(huì)對分級(jí)存儲(chǔ)帶來限制。按照 JuiceFS 的處理,當(dāng)文件存儲(chǔ)在對象存儲(chǔ)上時(shí),它被邏輯上拆分為許多 chunks、slices 和 blocks,最終以 block 的形式存儲(chǔ)在對象存儲(chǔ)中。
JuiceFS 數(shù)據(jù)分塊示意圖
因此,如果我們觀察對象存儲(chǔ)中的文件,實(shí)際上無法直接找到文件本身,而只能看到被分割成的小塊。即使 OSS 提供了聲明周期管理功能,但我們也無法基于表、分區(qū)或文件級(jí)別進(jìn)行生命周期的配置。
后續(xù)我們通過以下這種方式來解決。
兩個(gè) bucket:標(biāo)準(zhǔn)( JuiceFS ) + 低頻(OSS):創(chuàng)建兩個(gè)存儲(chǔ)桶,一個(gè)存儲(chǔ)桶用于 JuiceFS,并將所有數(shù)據(jù)存儲(chǔ)在標(biāo)準(zhǔn)存儲(chǔ)層中。另外,我們額外創(chuàng)建一個(gè)低頻的 OSS 存儲(chǔ)桶。
基于業(yè)務(wù)邏輯,對表 / 分區(qū) / 文件,配置存儲(chǔ)策略表。我們可以根據(jù)表、分區(qū)或文件來設(shè)置存儲(chǔ)策略,并編寫定時(shí)任務(wù)來掃描并執(zhí)行這些策略。
用 Juicesync 將低頻文件從 JuiceFS 導(dǎo)出到 OSS 并修改 Hive 元數(shù)據(jù)。文件從 JuiceFS 轉(zhuǎn)移到 OSS 之后會(huì)從 JuiceFS 刪除,并且在 OSS 上能看到完整的文件內(nèi)容,我們就可以對其設(shè)置生命周期規(guī)則。轉(zhuǎn)移完文件后需要及時(shí)修改 Hive 元數(shù)據(jù),,將 Hive 表或分區(qū)的位置更改為新的 OSS 地址。EMR 的 Hive/Impala/Spark 等組件原生支持 OSS,因此應(yīng)用層基本無感(需注意訪問低頻文件會(huì)帶來額外開銷)。
完成這個(gè)操作后,除了實(shí)現(xiàn)分級(jí)存儲(chǔ)以降低成本外,還有一個(gè)額外的好處是我們可以減少 JuiceFS 元數(shù)據(jù)的數(shù)量。因?yàn)檫@些文件不再屬于 JuiceFS,而是由 OSS 直接管理,這意味著 JuiceFS 中的 inode 數(shù)量會(huì)減少,元數(shù)據(jù)的管理壓力就會(huì)減輕,Redis 請求的數(shù)量和容量也會(huì)降低。從穩(wěn)定性的角度來看,這對系統(tǒng)會(huì)更有利。
架構(gòu)升級(jí)的收益 & 后續(xù)計(jì)劃 存算分離的收益
總的存儲(chǔ)量增長了兩倍,計(jì)算資源不動(dòng),偶爾開啟臨時(shí)的任務(wù)節(jié)點(diǎn)。在我們的場景中,數(shù)據(jù)量增長非???,但查詢需求相對穩(wěn)定。從 2021 年至今,數(shù)據(jù)量已增長兩倍。計(jì)算資源在初始階段至今基本沒有做過太多的改動(dòng),除非出于某些業(yè)務(wù)需求需要更快的計(jì)算速度,我們會(huì)開啟彈性資源和臨時(shí)任務(wù)節(jié)點(diǎn)來加速。
性能變化
總體無明顯感知,PoC 期間做過簡單的 TPCDS 測試顯示差異不大,ad-hoc 的 Impala 查詢響應(yīng)變快了
影響因素多:HDFS -> JuiceFS、組件版本升級(jí)、Hive 計(jì)算引擎變化、集群負(fù)載等
在我們的業(yè)務(wù)場景中,主要是進(jìn)行大數(shù)據(jù)的批處理離線計(jì)算,總體而言對于性能的延遲并不敏感。
在 PoC 期間,我們進(jìn)行了一些簡單的測試。然而,這些測試很難準(zhǔn)確說明問題,因?yàn)闇y試過程受到了許多影響因素的影響。我們首先更換了存儲(chǔ)系統(tǒng),從 HDFS 切換到了 JuiceFS,同時(shí)進(jìn)行了組件版本升級(jí),Hive 引擎也發(fā)生了變化。此外,集群負(fù)載也無法完全一致。在我們的場景中,與之前在物理服務(wù)器上部署的 CDH 相比,集群架構(gòu)的性能差異并不明顯。
易用性 & 穩(wěn)定性
JuiceFS 本身沒出過問題
EMR 的使用有遇到些小問題,總體上 CDH 更穩(wěn)定易用
實(shí)施復(fù)雜度
我們的場景里, 增量雙寫 & 數(shù)據(jù)校驗(yàn)過程花的時(shí)間最多(回過頭看校驗(yàn)的投入過大,可以精簡) ;
影響因素多:跟業(yè)務(wù)場景(離線 / 實(shí)時(shí)、表 / 任務(wù)數(shù)量、上層應(yīng)用)、組件版本、配套工具和儲(chǔ)備。
當(dāng)評(píng)估類似架構(gòu)或方案的復(fù)雜度時(shí),有許多影響因素需要考慮。其中包括業(yè)務(wù)場景的差異,以及對延遲要求的敏感程度不同。此外,表數(shù)據(jù)量的規(guī)模也會(huì)產(chǎn)生影響。在我們的場景中,我們有大量的表和數(shù)據(jù)庫,文件數(shù)量相對較多。此外,上層應(yīng)用程序的特性、使用業(yè)務(wù)的數(shù)量以及相關(guān)程序等也會(huì)對復(fù)雜度產(chǎn)生影響。另一個(gè)重要的影響因素是版本遷移的逐漸差異。如果只進(jìn)行平移而保持版本不變,那么組件的影響基本上可以消除。
配套工具和儲(chǔ)備是一個(gè)重要的影響因素。在進(jìn)行數(shù)倉或 ETL 任務(wù)時(shí),有多種實(shí)現(xiàn)方式可供選擇,例如手動(dòng)編寫 Hive SQL 文件、Python 或 Java 程序,或者使用常見的調(diào)度工具。但無論采用哪種方式,我們都需要復(fù)制和修改這些程序,因?yàn)殡p寫是必要的。
我們使用自研的開發(fā)平臺(tái) OneWork,在任務(wù)配置方面非常完善。通過 OneWork 平臺(tái),用戶可以在 Web 界面上配置這些任務(wù),從而實(shí)現(xiàn)統(tǒng)一管理。Spark 任務(wù)的部署也無需登錄到服務(wù)器上操作,OneWork 會(huì)自動(dòng)提交到 Yarn 集群。這個(gè)平臺(tái)大大簡化了代碼配置和修改的過程。我們編寫了一個(gè)腳本將任務(wù)配置復(fù)制出來,進(jìn)行一些修改,就可以實(shí)現(xiàn)高度的自動(dòng)化程度,幾乎達(dá)到百分之八九十,從而順利運(yùn)行這些任務(wù)。
后續(xù)計(jì)劃大致有幾個(gè)方向:
繼續(xù)完成剩余業(yè)務(wù)的上云遷移;
探索 JuiceFS + OSS 的冷熱分級(jí)存儲(chǔ)策略。JuiceFS 的文件在 OSS 上完全被打散,無法基于文件級(jí)別做分級(jí)。目前的思路是將冷數(shù)據(jù)從 JuiceFS 遷移到 OSS 上,設(shè)置為歸檔存儲(chǔ),修改 Hive 表或分區(qū)的 LOCATION,不影響使用;
目前 JuiceFS 使用 Redis 作為元數(shù)據(jù)引擎,假如將來數(shù)據(jù)量增加,使用 Redis 有壓力的話可能考慮切換為 TiKV 或其他引擎;
探索 EMR 的彈性計(jì)算實(shí)例,爭取能在滿足業(yè)務(wù) SLA 的前提下降低使用成本。
附錄 部署和配置 關(guān)于 IDC- 阿里云專線:
能提供專線服務(wù)的供應(yīng)商很多,包括 IDC、阿里云、運(yùn)營商等,選擇的時(shí)候主要考慮線路質(zhì)量、成本、施工周期等因素,最終我們選擇了 IDC 的方案。IDC 跟阿里云有合作,很快就完成了專線的開通。這方面如果遇到問題,可以找 IDC 和阿里云的支持。除專線租用成本,阿里云也會(huì)收取下行(從阿里云到 IDC)方向傳輸費(fèi)用。專線兩端的內(nèi)網(wǎng) IP 完全互通,阿里云和 IDC 兩側(cè)都需要一些路由配置。
關(guān)于 EMR Core/Task 節(jié)點(diǎn)類型的選擇:
JuiceFS 可以使用本地硬盤做緩存[7],能進(jìn)一步減少 OSS 帶寬需求并提高 EMR 性能。更大的本地存儲(chǔ)空間,可以提供更高的緩存命中率。
阿里云本地 SSD 實(shí)例是較高性價(jià)比的 SSD 存儲(chǔ)方案(相對于云盤),用作緩存正合適。JuiceFS 社區(qū)版未支持分布式緩存,意味著每一個(gè)節(jié)點(diǎn)都需要一個(gè)緩存池,所以應(yīng)該選用盡量大的節(jié)點(diǎn)。
基于以上考慮和配置對比,我們決定選用 ecs.i2.16xlarge,每個(gè)節(jié)點(diǎn) 64 vCore、512GiB Memory、1.8T*8 SSD。
關(guān)于 EMR 版本:
軟件方面,主要包括確定組件版本、開啟集群、修改配置。我們機(jī)房使用的是 CDH 5.14,其中 Hadoop 版本是 2.6,阿里云上最接近的版本是 EMR 3.38. 但調(diào)研時(shí)發(fā)現(xiàn)該版本的 Impala 和 Ranger 不兼容(實(shí)際上我們機(jī)房使用的是 Sentry 做權(quán)限管理,但 EMR 上沒有),最終經(jīng)過評(píng)估對比,決定直接使用 EMR 5 的最新版,幾乎所有組件的大版本都做了升級(jí)(包含 Hadoop 3、Spark 3 和 Impala 3.4)。此外,使用外部 MySQL 作為 Hive Metastore、Hue、Ranger 的數(shù)據(jù)庫。
關(guān)于 JuiceFS 配置:
基本參考 JuiceFS 官方文檔《在 Hadoop 中通過 Java 客戶端訪問 JuiceFS[8]》即可完成配置。另外我們也配置了這些參數(shù):
緩存相關(guān):其中最重要的是 juicefs.cache-dir 緩存目錄。這個(gè)參數(shù)支持通配符,對多個(gè)硬盤的實(shí)例環(huán)境很友好,如設(shè)置為/mnt/disk*/juicefs-cache(需要手動(dòng)創(chuàng)建目錄,或在 EMR 節(jié)點(diǎn)初始腳本中創(chuàng)建),即用全部本地 SSD 作為緩存。另外也要關(guān)注 juicefs.cache-size、juicefs.free-space 兩個(gè)參數(shù)。
juicefs.push-gateway:設(shè)置一個(gè) Prometheus Push Gateway,用于采集 JuiceFS Java 客戶端的指標(biāo)。
juicefs.users、juicefs.groups:分別設(shè)置為 JuiceFS 中的一個(gè)文件(如 jfs://emr/etc/users、jfs://emr/etc/groups),解決多個(gè)節(jié)點(diǎn) uid 和 gid 可能不統(tǒng)一的問題。
關(guān)于 Kafka Connect 使用 JuiceFS:
經(jīng)過一些測試,確認(rèn) JuiceFS 可以完美應(yīng)用于 Kafka Connect 的 HDFS Sink 插件(我們把配置方式也補(bǔ)充到了官方文檔[9])。相比使用 HDFS Sink 寫入 HDFS,寫入 JuiceFS 需要增加或修改以下配置項(xiàng):
將 JuiceFS Java SDK 的 JAR 包發(fā)布到 Kafka Connect 每一個(gè)節(jié)點(diǎn)的 HDFS Sink 插件目錄。Confluent 平臺(tái)的插件路徑是:/usr/share/java/confluentinc-kafka-connect-hdfs/lib
編寫包含 JuiceFS 配置的 core-site.xml,發(fā)布到 Kafka Connect 每一個(gè)節(jié)點(diǎn)的任意目錄。包括這些必須配置的項(xiàng)目:
fs.jfs.impl = io.juicefs.JuiceFileSystem fs.AbstractFileSystem.jfs.impl = io.juicefs.JuiceFS juicefs.meta = redis://:password@my.redis.com:6379/1
請參見 JuiceFS Java SDK 的配置文檔。
Kafka Connector 任務(wù)設(shè)置:
hadoop.conf.dir=一手運(yùn)維經(jīng)驗(yàn)store.url=jfs:// /<路徑>
在整個(gè)實(shí)施過程中陸陸續(xù)續(xù)踩了一些坑,積累了一些經(jīng)驗(yàn),分享給大家做參考。
阿里云 EMR 和組件相關(guān)
兼容性
EMR 5 的 Hive 和 Spark 版本不兼容,無法使用 Hive on Spark,可以把默認(rèn)的引擎改成 Hive on Tez.
Impala 的 stats 數(shù)據(jù)從舊版同步到新版后,可能因?yàn)?IMPALA-10230[10] 導(dǎo)致表無法查詢。解決方案是在同步元數(shù)據(jù)時(shí),將 num_nulls=-1 的改成 num_nulls=0. 可能需要用到 CatalogObjects.thrift[11] 文件。
原集群有少量 Textfile 格式的文件用了 snappy 壓縮,新版 Impala 無法讀取,報(bào)錯(cuò) Snappy: RawUncompress failed,可能是 IMPALA-10005[12] 導(dǎo)致的。規(guī)避方案是不要對 Textfile 文件使用 snappy 壓縮。
Impala 3.4 相比 2.11 的 CONCAT_WS 函數(shù)行為有差異,老版本 CONCAT_WS('_', 'abc', NULL) 會(huì)返回 NULL,而新版本返回 'abc'.
Impala 3.4 對 SQL 中的保留關(guān)鍵字引用更嚴(yán)格,必須加上 “''”. 其實(shí)一個(gè)好習(xí)慣是業(yè)務(wù)代碼不要使用保留關(guān)鍵字。
PoC 或前期測試的覆蓋度盡可能完整,用真實(shí)的業(yè)務(wù)代碼去跑。我們在 PoC 和早期遷移的業(yè)務(wù)中用到的組件特性比較少,基本都是最常用、保持兼容的功能,因此比較順利。但在第二批遷移過程中就暴露出了很多問題,雖然最終都有解決,但花了很多額外的時(shí)間去做診斷和定位,打亂了節(jié)奏。
性能
EMR 5 的 Impala 3.4 打了 IMPALA-10695[13] 這個(gè)補(bǔ)丁,支持對 oss:// 和 jfs://(本意是支持 JindoFS,但 JuiceFS 也默認(rèn)使用 jfs 這個(gè) scheme)設(shè)置獨(dú)立的 IO 線程數(shù)。在 EMR 控制臺(tái)上增加或修改 Impala 的配置項(xiàng) num_oss_io_threads.
阿里云 OSS 有賬號(hào)級(jí)別的帶寬限制,默認(rèn) 10Gbps,隨著業(yè)務(wù)規(guī)模上升容易成為瓶頸??梢耘c阿里云溝通調(diào)整。
運(yùn)維
EMR 可以關(guān)聯(lián)一個(gè) Gateway 集群,通常用來部署業(yè)務(wù)程序。如果要在 Gateway 上用 client 模式提交 Spark 任務(wù),需要先將 Gateway 機(jī)器的 IP 加到 EMR 節(jié)點(diǎn)的 hosts 文件。默認(rèn)可以使用 cluster 模式。
EMR 5 會(huì)開啟一個(gè) Spark ThriftServer,在 Hue 上可以直接寫 Spark SQL,用起來很方便。但默認(rèn)配置有個(gè)坑,會(huì)寫大量日志(路徑大概是 /mnt/disk1/log/spark/spark-hadoop-org.apache.spark.sql.hive.thriftserver.HiveThriftServer2-1-emr-header-1.cluster-xxxxxx.out),導(dǎo)致硬盤寫滿。解決方案有兩個(gè):配置 log rotate 或把 spark.driver.extraJavaOptions 配置清空(阿里云技術(shù)支持的建議)。
JuiceFS 相關(guān)
JuiceFS 需要每個(gè)節(jié)點(diǎn)上具有相同的 UID 和 GID,否則很容易出現(xiàn)權(quán)限問題。有兩種實(shí)現(xiàn)方式:修改操作系統(tǒng)的用戶[14](比較適合新機(jī)器,沒有歷史包袱),或者在 JuiceFS 上維護(hù)一個(gè)用戶映射表[15]。我們之前也分享過一篇 JuiceFS + HDFS 權(quán)限問題定位[16],有詳細(xì)討論。通常需要維護(hù)映射的用戶有 impala, hive, hadoop 等。如果使用 Confluent Platform 搭建 Kafka Connect,也需要配置 cp-kafka-connect 用戶。
使用默認(rèn)的 JuiceFS IO 配置[17] 時(shí),相同的寫查詢,Hive on Tez 和 Spark 都比 Impala 快很多(但在機(jī)房里 Impala 更快)。最終發(fā)現(xiàn)將 juicefs.memory-size 從默認(rèn)的 300 (MiB) 改成 1024 之后 Impala 的寫入性能有成倍的提升。
在做 JuiceFS 的問題診斷和分析時(shí),客戶端日志很有用,需要注意 POSIX 和 Java SDK 的日志是不一樣的,詳見 JuiceFS 故障診斷和分析 | JuiceFS Document Center[18]
注意監(jiān)控 Redis 的空間用量,Redis 如果滿了,整個(gè) JuiceFS 集群無法寫入。(這點(diǎn)需要特別注意) 使用 JuiceFS sync 把機(jī)房數(shù)據(jù)往云上同步時(shí),選擇在有 SSD 的機(jī)器上跑,獲得更好的性能。
審核編輯:劉清
-
存儲(chǔ)器
+關(guān)注
關(guān)注
38文章
7435瀏覽量
163526 -
MYSQL數(shù)據(jù)庫
+關(guān)注
關(guān)注
0文章
95瀏覽量
9375 -
tpc
+關(guān)注
關(guān)注
0文章
15瀏覽量
10523 -
HDFS
+關(guān)注
關(guān)注
1文章
30瀏覽量
9560 -
AWS
+關(guān)注
關(guān)注
0文章
427瀏覽量
24290
原文標(biāo)題:Hadoop 上云: 存算分離架構(gòu)設(shè)計(jì)與遷移實(shí)踐
文章出處:【微信號(hào):AI前線,微信公眾號(hào):AI前線】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評(píng)論請先 登錄
相關(guān)推薦
評(píng)論