背景
一面數(shù)據(jù)創(chuàng)立于 2014 年纵散,是一家領(lǐng)先的數(shù)據(jù)智能解決方案提供商,通過解讀來自電商平臺和社交媒體渠道的海量數(shù)據(jù)隐圾,提供實時伍掀、全面的數(shù)據(jù)洞察。長期服務(wù)全球快消巨頭(寶潔暇藏、聯(lián)合利華蜜笤、瑪氏等),獲得行業(yè)廣泛認(rèn)可盐碱。公司與阿里把兔、京東、字節(jié)合作共建多個項目瓮顽,旗下知乎數(shù)據(jù)專欄“數(shù)據(jù)冰山”擁有超30萬粉絲县好。一面所屬艾盛集團(tuán)(Ascential)在倫敦證券交易所上市,在 120 多個國家為客戶提供本地化專業(yè)服務(wù)暖混。
公司在 2016 年線下機(jī)房部署了 CDH 集群缕贡,到 2021 年已存儲和處理 PB 級的數(shù)據(jù)。公司自創(chuàng)立以來一直保持每年翻一番的高增長拣播,而比業(yè)務(wù)量增長更快的是 Hadoop 集群的數(shù)據(jù)量晾咪。
在這幾年間,按 1 到 2 年規(guī)劃的硬件贮配,往往因數(shù)據(jù)增長超出預(yù)期而在半年后不得不再次擴(kuò)容谍倦。每次擴(kuò)容周期可達(dá)到一個月,除了花費大量精力跟進(jìn)行政和技術(shù)流程牧嫉,業(yè)務(wù)端也不得不安排較多人日控制數(shù)據(jù)量剂跟。
為了降低運(yùn)維難度减途,發(fā)展可持續(xù)擴(kuò)張的大數(shù)據(jù)處理方案,我們從 2021 年 10 月份開始探索取代現(xiàn)有Hadoop 集群的方案曹洽。當(dāng)時提出了這些需求:
- 上云鳍置,彈性伸縮、靈活運(yùn)維
- 存儲計算分離
- 盡量使用開源組件送淆,避免云廠商綁定
- 盡量降低業(yè)務(wù)遷移工作量
最終選擇的方案是使用阿里云 EMR + JuiceFS + 阿里云 OSS 來搭建存算分離的大數(shù)據(jù)平臺税产,將云下數(shù)據(jù)中心的業(yè)務(wù)逐步遷移上云。截至目前(2022 年 7 月)整體遷移進(jìn)度約 40%偷崩,計劃在 2022 年內(nèi)完成全部業(yè)務(wù)的搬遷辟拷,屆時云上 EMR 的數(shù)據(jù)量預(yù)計會超過單副本 1 PB.
技術(shù)選型
首先是決定使用哪家云廠商。由于業(yè)務(wù)需求阐斜,AWS衫冻、Azure 和阿里云都有在用,綜合考慮后認(rèn)為阿里云最適合谒出,有這些因素:
- 物理距離:阿里云在我們線下機(jī)房同城有可用區(qū)隅俘,網(wǎng)絡(luò)專線的延遲小,成本低
- 開源組件齊全:阿里云 EMR 上包含的開源組件很多很全笤喳,除了我們重度使用的 Hive为居、Impala、Spark杀狡、Hue蒙畴,也能方便集成 Presto、Hudi呜象、Iceberg 等膳凝。我們在調(diào)研時發(fā)現(xiàn)只有阿里云 EMR 自帶了 Impala,AWS 和 Azure 要么版本低董朝,要么要自己安裝部署鸠项。
阿里云的 EMR 本身也有使用 JindoFS 的存算分離方案,但基于以下考慮子姜,我們最終選擇了JuiceFS:
- JuiceFS 使用 Redis 和對象存儲為底層存儲,客戶端完全是無狀態(tài)的楼入,可以在不同環(huán)境訪問同一個文件系統(tǒng)哥捕,提高了方案的靈活性。而 JindoFS 元數(shù)據(jù)存儲在 EMR 集群的本地硬盤嘉熊,不便于維護(hù)遥赚、升級和遷移。
- JuiceFS 的存儲方案豐富阐肤,而且支持不同方案的在線遷移凫佛,提高了方案的可移植性讲坎。JindoFS 塊數(shù)據(jù)只支持 OSS.
- JuiceFS 以開源社區(qū)為基礎(chǔ),支持所有公有云環(huán)境愧薛,方便后期擴(kuò)展到多云架構(gòu)晨炕。
關(guān)于 JuiceFS
直接截取官方文檔的介紹:
JuiceFS 是一款面向云原生設(shè)計的高性能共享文件系統(tǒng),在 Apache 2.0 開源協(xié)議下發(fā)布毫炉。提供完備的 POSIX 兼容性瓮栗,可將幾乎所有對象存儲接入本地作為海量本地磁盤使用,亦可同時在跨平臺瞄勾、跨地區(qū)的不同主機(jī)上掛載讀寫费奸。
JuiceFS 采用「數(shù)據(jù)」與「元數(shù)據(jù)」分離存儲的架構(gòu),從而實現(xiàn)文件系統(tǒng)的分布式設(shè)計进陡。使用 JuiceFS 存儲數(shù)據(jù)愿阐,數(shù)據(jù)本身會被持久化在對象存儲(例如,Amazon S3)趾疚,相對應(yīng)的元數(shù)據(jù)可以按需持久化在 Redis换况、MySQL、TiKV盗蟆、SQLite 等多種數(shù)據(jù)庫中戈二。
除了 POSIX 之外,JuiceFS 完整兼容 HDFS SDK喳资,與對象存儲結(jié)合使用可以完美替換 HDFS觉吭,實現(xiàn)存儲和計算分離。
實施過程
我們在 2021 年 10 月開始探索 Hadoop 的上云方案仆邓;11 月做了大量調(diào)研和討論鲜滩,基本確定方案內(nèi)容;12 月和 2022 年 1 月春節(jié)前做了 PoC 測試节值,在春節(jié)后 3 月份開始搭建正式環(huán)境并安排遷移徙硅。為了避免導(dǎo)致業(yè)務(wù)中斷,整個遷移過程以相對較慢的節(jié)奏分階段執(zhí)行搞疗,截至目前(2022 年 7 月)進(jìn)度約 40%嗓蘑,計劃在 2022 年內(nèi)完成整體的搬遷。 遷移完后匿乃,云上的 EMR 集群數(shù)據(jù)量預(yù)計會超過單副本 1 PB.
架構(gòu)設(shè)計
做完技術(shù)選型之后桩皿,架構(gòu)設(shè)計也能很快確定下來〈闭ǎ考慮到除了 Hadoop 上云之外泄隔,仍然有大部分業(yè)務(wù)會繼續(xù)保留在數(shù)據(jù)中心,所以整體實際上是個混合云的架構(gòu)宛徊。
部署和配置
- 關(guān)于IDC-阿里云專線:能提供專線服務(wù)的供應(yīng)商很多佛嬉,包括 IDC逻澳、阿里云、運(yùn)營商等暖呕,選擇的時候主要考慮線路質(zhì)量斜做、成本、施工周期等因素缰揪,最終我們選擇了IDC的方案陨享。IDC 跟阿里云有合作,很快就完成了專線的開通钝腺。這方面如果遇到問題抛姑,可以找 IDC 和阿里云的支持。除專線租用成本艳狐,阿里云也會收取下行(從阿里云到 IDC)方向傳輸費用定硝。專線兩端的內(nèi)網(wǎng) IP 完全互通,阿里云和 IDC 兩側(cè)都需要一些路由配置毫目。
- 關(guān)于EMR Core/Task 節(jié)點類型的選擇:
- JuiceFS 可以使用本地硬盤做緩存蔬啡,能進(jìn)一步減少 OSS 帶寬需求并提高 EMR 性能。更大的本地存儲空間镀虐,可以提供更高的緩存命中率箱蟆。
- 阿里云本地 SSD 實例是較高性價比的 SSD 存儲方案(相對于云盤),用作緩存正合適刮便。
- JuiceFS 社區(qū)版未支持分布式緩存空猜,意味著每一個節(jié)點都需要一個緩存池,所以應(yīng)該選用盡量大的節(jié)點恨旱。
基于以上考慮和配置對比辈毯,我們決定選用 ecs.i2.16xlarge,每個節(jié)點64 vCore搜贤、512GiB Memory谆沃、1.8T*8 SSD。
關(guān)于 EMR 版本:
軟件方面仪芒,主要包括確定組件版本唁影、開啟集群、修改配置桌硫。我們機(jī)房使用的是 CDH 5.14夭咬,其中 Hadoop 版本是 2.6,阿里云上最接近的版本是 EMR 3.38. 但調(diào)研時發(fā)現(xiàn)該版本的 Impala 和 Ranger 不兼容(實際上我們機(jī)房使用的是 Sentry 做權(quán)限管理铆隘,但 EMR 上沒有),最終經(jīng)過評估對比南用,決定直接使用 EMR 5 的最新版膀钠,幾乎所有組件的大版本都做了升級(包含 Hadoop 3掏湾、Spark 3 和 Impala 3.4)。此外肿嘲,使用外部 MySQL 作為 Hive Metastore融击、Hue、Ranger 的數(shù)據(jù)庫雳窟。關(guān)于 JuiceFS 配置:
基本參考JuiceFS官方文檔《在 Hadoop 中通過 Java 客戶端訪問 JuiceFS》即可完成配置。另外我們也配置了這些參數(shù):緩存相關(guān):其中最重要的是
juicefs.cache-dir
緩存目錄。這個參數(shù)支持通配符潘飘,對多個硬盤的實例環(huán)境很友好杏慰,如設(shè)置為/mnt/disk*/juicefs-cache
(需要手動創(chuàng)建目錄,或在EMR節(jié)點初始腳本中創(chuàng)建)誉结,即用全部本地 SSD 作為緩存鹅士。另外也要關(guān)注juicefs.cache-size
、juicefs.free-space
兩個參數(shù)惩坑。juicefs.push-gateway
:設(shè)置一個 Prometheus Push Gateway掉盅,用于采集 JuiceFS Java 客戶端的指標(biāo)。juicefs.users
以舒、juicefs.groups
:分別設(shè)置為 JuiceFS 中的一個文件(如jfs://emr/etc/users
趾痘、jfs://emr/etc/groups
),解決多個節(jié)點 uid 和 gid 可能不統(tǒng)一的問題蔓钟。關(guān)于 Kafka Connect 使用 JuiceFS:
經(jīng)過一些測試永票,確認(rèn) JuiceFS 可以完美應(yīng)用于 Kafka Connect 的 HDFS Sink 插件(我們把配置方式也補(bǔ)充到了官方文檔)。相比使用 HDFS Sink 寫入HDFS奋刽,寫入 JuiceFS 需要增加或修改以下配置項:
- 將 JuiceFS Java SDK 的 JAR 包發(fā)布到 Kafka Connect 每一個節(jié)點的 HDFS Sink 插件目錄瓦侮。Confluent 平臺的插件路徑是:
/usr/share/java/confluentinc-kafka-connect-hdfs/lib
- 編寫包含 JuiceFS 配置的
core-site.xml
,發(fā)布到 Kafka Connect 每一個節(jié)點的任意目錄佣谐。包括這些必須配置的項目:
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=<core-site.xml所在目錄>
store.url=jfs://<JuiceFS文件系統(tǒng)名稱>/<路徑>
PoC
PoC 的目的是快速驗證方案的可行性,有幾個具體目標(biāo):
- 驗證 EMR + JuiceFS + OSS 整體方案的可行性
- 檢查 Hive狭魂、Impala罚攀、Spark、Ranger 等組件版本的兼容性
- 評估對比性能表現(xiàn)雌澄,用了 TPC-DS 的測試用例和部分內(nèi)部真實業(yè)務(wù)場景斋泄,沒有非常精確的對比,但能滿足業(yè)務(wù)需求
- 評估生產(chǎn)環(huán)境所需的節(jié)點實例類型和數(shù)量(算成本)
- 探索數(shù)據(jù)同步方案
- 探索驗證集群與自研 ETL 平臺镐牺、Kafka Connect 等的集成方案
期間做了大量測試炫掐、文檔調(diào)研、內(nèi)外部(阿里云 + JuiceFS 團(tuán)隊)討論睬涧、源碼理解募胃、工具適配等工作旗唁,最終決定繼續(xù)推進(jìn)。
數(shù)據(jù)同步
要遷移的數(shù)據(jù)包括兩部分:Hive Metastore 元數(shù)據(jù)以及 HDFS 上的文件痹束。由于不能中斷業(yè)務(wù)检疫,采用存量同步 + 增量同步(雙寫)的方式進(jìn)行遷移;數(shù)據(jù)同步完后需要進(jìn)行一致性校驗祷嘶。
存量同步
對于存量文件同步屎媳,可以使用 JuiceFS 提供的功能完整的數(shù)據(jù)同步工具 sync 子命令 來實現(xiàn)高效遷移。JuiceFS sync 命令支持單節(jié)點和多機(jī)并發(fā)同步论巍,實際使用時發(fā)現(xiàn)單節(jié)點開多線程即可打滿專線帶寬烛谊,CPU 和內(nèi)存占用低,性能表現(xiàn)非常不錯环壤。
Hive Metastore 的數(shù)據(jù)同步則相對麻煩些:
- 兩個 Hive 版本不一致晒来,Metastore 的表結(jié)構(gòu)有差異,因此無法直接使用 MySQL 的導(dǎo)出導(dǎo)入功能
- 遷移后需要修改庫郑现、表湃崩、分區(qū)存儲路徑(即
dbs
表的DB_LOCATION_URI
和sds
表的LOCATION
)
因此我們開發(fā)了一套腳本工具,支持表和分區(qū)粒度的數(shù)據(jù)同步接箫,使用起來很方便攒读。
增量同步
增量數(shù)據(jù)主要來自兩個場景:Kafka Connect HDFS Sink 和 ETL 程序,我們采用了雙寫機(jī)制辛友。
Kafka Connect 的 Sink 任務(wù)都復(fù)制一份即可薄扁,配置方式上文有介紹。ETL 任務(wù)統(tǒng)一在內(nèi)部自研的低代碼平臺上開發(fā)废累,底層使用 Airflow 進(jìn)行調(diào)度邓梅。通常只需要把相關(guān)的 DAG 復(fù)制一份,修改集群地址即可邑滨。實際遷移過程中日缨,這一步遇到的問題最多,花了大量時間來解決掖看。主要原因是 Spark匣距、Impala、Hive 組件版本的差異導(dǎo)致任務(wù)出錯或數(shù)據(jù)不一致哎壳,需要修改業(yè)務(wù)代碼毅待。這些問題在 PoC 和早期的遷移中沒有覆蓋到,算是個教訓(xùn)归榕。
數(shù)據(jù)校驗
數(shù)據(jù)同步完后需要進(jìn)行一致性校驗尸红,分三層:
- 文件一致。在存量同步階段做校驗,通常的方式是用 checksum. 最初的 JuiceFS sync 命令不支持 checksum 機(jī)制驶乾,我們建議和討論后邑飒,JuiceFS 團(tuán)隊很快就加上了該功能(issue循签,pull request)级乐。除了 checksum,也可考慮使用文件屬性對比的方式:確保兩個文件系統(tǒng)里所有文件的數(shù)量县匠、修改時間风科、屬性一致。比 checksum 的可靠性稍弱乞旦,但更輕量快捷贼穆。
- 元數(shù)據(jù)一致。有兩種思路:對比 Metastore 數(shù)據(jù)庫的數(shù)據(jù)兰粉,或?qū)Ρ?Hive 的 DDL 命令的結(jié)果故痊。
- 計算結(jié)果一致。即使用 Hive/Impala/Spark 跑一些查詢玖姑,對比兩邊的結(jié)果是否一致愕秫。一些可以參考的查詢:表/分區(qū)的行數(shù)、基于某個字段的排序結(jié)果焰络、數(shù)值字段的最大/最小/平均值戴甩、業(yè)務(wù)中經(jīng)常使用的統(tǒng)計聚合等。
數(shù)據(jù)校驗的功能也封裝到了腳本里闪彼,方便快速發(fā)現(xiàn)數(shù)據(jù)問題甜孤。
后續(xù)計劃
大致有幾個方向:
- 繼續(xù)完成剩余業(yè)務(wù)的上云遷移
- 探索 JuiceFS + OSS 的冷熱分級存儲策略。JuiceFS 的文件在 OSS 上完全被打散畏腕,無法基于文件級別做分級缴川。目前的思路是將冷數(shù)據(jù)從 JuiceFS 遷移到 OSS 上,設(shè)置為歸檔存儲描馅,修改 Hive 表或分區(qū)的 LOCATION把夸,不影響使用。
- 目前 JuiceFS 使用 Redis 作為元數(shù)據(jù)引擎流昏,假如將來數(shù)據(jù)量增加扎即,使用 Redis 有壓力的話可能考慮切換為 TiKV 或其他引擎。
- 探索 EMR 的彈性計算實例况凉,爭取能在滿足業(yè)務(wù) SLA 的前提下降低使用成本
一手實戰(zhàn)經(jīng)驗
在整個實施過程中陸陸續(xù)續(xù)踩了一些坑谚鄙,積累了一些經(jīng)驗,分享給大家做參考刁绒。
阿里云 EMR 和組件相關(guān)
兼容性
- EMR 5 的 Hive 和 Spark 版本不兼容闷营,無法使用 Hive on Spark,可以把默認(rèn)的引擎改成 Hive on Tez.
- Impala 的 stats 數(shù)據(jù)從舊版同步到新版后,可能因為 IMPALA-10230 導(dǎo)致表無法查詢傻盟。解決方案是在同步元數(shù)據(jù)時速蕊,將
num_nulls=-1
的改成num_nulls=0
. 可能需要用到 CatalogObjects.thrift 文件。 - 原集群有少量 Textfile 格式的文件用了 snappy 壓縮娘赴,新版 Impala 無法讀取规哲,報錯
Snappy: RawUncompress failed
,可能是 IMPALA-10005 導(dǎo)致的诽表。規(guī)避方案是不要對 Textfile 文件使用 snappy 壓縮唉锌。 - Impala 3.4 相比 2.11 的
CONCAT_WS
函數(shù)行為有差異,老版本CONCAT_WS('_', 'abc', NULL)
會返回NULL
竿奏,而新版本返回'abc'
. - Impala 3.4 對 SQL 中的保留關(guān)鍵字引用更嚴(yán)格袄简,必須加上``. 其實一個好習(xí)慣是業(yè)務(wù)代碼不要使用保留關(guān)鍵字。
- PoC 或前期測試的覆蓋度盡可能完整泛啸,用真實的業(yè)務(wù)代碼去跑绿语。我們在 PoC 和早期遷移的業(yè)務(wù)中用到的組件特性比較少,基本都是最常用候址、保持兼容的功能吕粹,因此比較順利。但在第二批遷移過程中就暴露出了很多問題宗雇,雖然最終都有解決昂芜,但花了很多額外的時間去做診斷和定位,打亂了節(jié)奏赔蒲。
性能
- EMR 5 的 Impala 3.4 打了 IMPALA-10695 這個補(bǔ)丁泌神,支持對
oss://
和jfs://
(本意是支持 JindoFS,但 JuiceFS 也默認(rèn)使用 jfs 這個 scheme)設(shè)置獨立的 IO 線程數(shù)舞虱。在 EMR 控制臺上增加或修改 Impala 的配置項num_oss_io_threads
. - 阿里云 OSS 有賬號級別的帶寬限制欢际,默認(rèn) 10Gbps,隨著業(yè)務(wù)規(guī)模上升容易成為瓶頸矾兜∷鹎鳎可以與阿里云溝通調(diào)整。
運(yùn)維
- EMR 可以關(guān)聯(lián)一個 Gateway 集群椅寺,通常用來部署業(yè)務(wù)程序浑槽。如果要在 Gateway 上用 client 模式提交 Spark 任務(wù),需要先將 Gateway 機(jī)器的 IP 加到 EMR 節(jié)點的 hosts 文件返帕。默認(rèn)可以使用 cluster 模式桐玻。
- EMR 5 會開啟一個 Spark ThriftServer,在 Hue 上可以直接寫 Spark SQL荆萤,用起來很方便镊靴。但默認(rèn)配置有個坑铣卡,會寫大量日志(路徑大概是
/mnt/disk1/log/spark/spark-hadoop-org.apache.spark.sql.hive.thriftserver.HiveThriftServer2-1-emr-header-1.cluster-xxxxxx.out
),導(dǎo)致硬盤寫滿偏竟。解決方案有兩個:配置 log rotate 或把spark.driver.extraJavaOptions
配置清空(阿里云技術(shù)支持的建議)煮落。
JuiceFS 相關(guān)
- JuiceFS 需要每個節(jié)點上具有相同的 UID 和 GID,否則很容易出現(xiàn)權(quán)限問題踊谋。有兩種實現(xiàn)方式:修改操作系統(tǒng)的用戶(比較適合新機(jī)器蝉仇,沒有歷史包袱),或者在 JuiceFS 上維護(hù)一個用戶映射表褪子。我們之前也分享過一篇 JuiceFS + HDFS 權(quán)限問題定位量淌,有詳細(xì)討論。通常需要維護(hù)映射的用戶有
impala
,hive
,hadoop
等嫌褪。如果使用 Confluent Platform 搭建 Kafka Connect,也需要配置cp-kafka-connect
用戶胚股。 - 使用默認(rèn)的 JuiceFS IO 配置時笼痛,相同的寫查詢,Hive on Tez 和 Spark 都比 Impala 快很多(但在機(jī)房里 Impala 更快)琅拌。最終發(fā)現(xiàn)將
juicefs.memory-size
從默認(rèn)的300
(MiB) 改成1024
之后 Impala 的寫入性能有成倍的提升缨伊。 - 在做 JuiceFS 的問題診斷和分析時,客戶端日志很有用进宝,需要注意 POSIX 和 Java SDK 的日志是不一樣的刻坊,詳見 JuiceFS 故障診斷和分析 | JuiceFS Document Center
- 注意監(jiān)控 Redis 的空間用量,Redis 如果滿了党晋,整個 JuiceFS 集群無法寫入谭胚。
- 使用 JuiceFS sync 把機(jī)房數(shù)據(jù)往云上同步時,選擇在有 SSD 的機(jī)器上跑未玻,獲得更好的性能灾而。
如有幫助的話歡迎關(guān)注我們項目 Juicedata/JuiceFS 喲! (0?0?)