一面數(shù)據(jù): Hadoop 遷移云上架構(gòu)設(shè)計(jì)與實(shí)踐

背景

一面數(shù)據(jù)創(chuàng)立于 2014 年,是一家領(lǐng)先的數(shù)據(jù)智能解決方案提供商,通過解讀來自電商平臺(tái)和社交媒體渠道的海量數(shù)據(jù),提供實(shí)時(shí)、全面的數(shù)據(jù)洞察。長(zhǎng)期服務(wù)全球快消巨頭(寶潔、聯(lián)合利華、瑪氏等),獲得行業(yè)廣泛認(rèn)可。公司與阿里、京東、字節(jié)合作共建多個(gè)項(xiàng)目,旗下知乎數(shù)據(jù)專欄“數(shù)據(jù)冰山”擁有超30萬粉絲。一面所屬艾盛集團(tuán)(Ascential)在倫敦證券交易所上市,在 120 多個(gè)國(guó)家為客戶提供本地化專業(yè)服務(wù)。

公司在 2016 年線下機(jī)房部署了 CDH 集群,到 2021 年已存儲(chǔ)和處理 PB 級(jí)的數(shù)據(jù)。公司自創(chuàng)立以來一直保持每年翻一番的高增長(zhǎng),而比業(yè)務(wù)量增長(zhǎng)更快的是 Hadoop 集群的數(shù)據(jù)量。

在這幾年間,按 1 到 2 年規(guī)劃的硬件,往往因數(shù)據(jù)增長(zhǎng)超出預(yù)期而在半年后不得不再次擴(kuò)容。每次擴(kuò)容周期可達(dá)到一個(gè)月,除了花費(fèi)大量精力跟進(jìn)行政和技術(shù)流程,業(yè)務(wù)端也不得不安排較多人日控制數(shù)據(jù)量。

為了降低運(yùn)維難度,發(fā)展可持續(xù)擴(kuò)張的大數(shù)據(jù)處理方案,我們從 2021 年 10 月份開始探索取代現(xiàn)有Hadoop 集群的方案。當(dāng)時(shí)提出了這些需求:

  • 上云,彈性伸縮、靈活運(yùn)維
  • 存儲(chǔ)計(jì)算分離
  • 盡量使用開源組件,避免云廠商綁定
  • 盡量降低業(yè)務(wù)遷移工作量

最終選擇的方案是使用阿里云 EMR + JuiceFS + 阿里云 OSS 來搭建存算分離的大數(shù)據(jù)平臺(tái),將云下數(shù)據(jù)中心的業(yè)務(wù)逐步遷移上云。截至目前(2022 年 7 月)整體遷移進(jìn)度約 40%,計(jì)劃在 2022 年內(nèi)完成全部業(yè)務(wù)的搬遷,屆時(shí)云上 EMR 的數(shù)據(jù)量預(yù)計(jì)會(huì)超過單副本 1 PB.

技術(shù)選型

首先是決定使用哪家云廠商。由于業(yè)務(wù)需求,AWS、Azure 和阿里云都有在用,綜合考慮后認(rèn)為阿里云最適合,有這些因素:

  • 物理距離:阿里云在我們線下機(jī)房同城有可用區(qū),網(wǎng)絡(luò)專線的延遲小,成本低
  • 開源組件齊全:阿里云 EMR 上包含的開源組件很多很全,除了我們重度使用的 Hive、Impala、Spark、Hue,也能方便集成 Presto、Hudi、Iceberg 等。我們?cè)谡{(diào)研時(shí)發(fā)現(xiàn)只有阿里云 EMR 自帶了 Impala,AWS 和 Azure 要么版本低,要么要自己安裝部署。

阿里云的 EMR 本身也有使用 JindoFS 的存算分離方案,但基于以下考慮,我們最終選擇了JuiceFS:

  1. JuiceFS 使用 Redis 和對(duì)象存儲(chǔ)為底層存儲(chǔ),客戶端完全是無狀態(tài)的,可以在不同環(huán)境訪問同一個(gè)文件系統(tǒng),提高了方案的靈活性。而 JindoFS 元數(shù)據(jù)存儲(chǔ)在 EMR 集群的本地硬盤,不便于維護(hù)、升級(jí)和遷移。
  2. JuiceFS 的存儲(chǔ)方案豐富,而且支持不同方案的在線遷移,提高了方案的可移植性。JindoFS 塊數(shù)據(jù)只支持 OSS.
  3. JuiceFS 以開源社區(qū)為基礎(chǔ),支持所有公有云環(huán)境,方便后期擴(kuò)展到多云架構(gòu)。

關(guān)于 JuiceFS

直接截取官方文檔的介紹:

JuiceFS 是一款面向云原生設(shè)計(jì)的高性能共享文件系統(tǒng),在 Apache 2.0 開源協(xié)議下發(fā)布。提供完備的 POSIX 兼容性,可將幾乎所有對(duì)象存儲(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ì)被持久化在對(duì)象存儲(chǔ)(例如,Amazon S3),相對(duì)應(yīng)的元數(shù)據(jù)可以按需持久化在 Redis、MySQL、TiKV、SQLite 等多種數(shù)據(jù)庫中。

除了 POSIX 之外,JuiceFS 完整兼容 HDFS SDK,與對(duì)象存儲(chǔ)結(jié)合使用可以完美替換 HDFS,實(shí)現(xiàn)存儲(chǔ)和計(jì)算分離。

實(shí)施過程

我們?cè)?2021 年 10 月開始探索 Hadoop 的上云方案;11 月做了大量調(diào)研和討論,基本確定方案內(nèi)容;12 月和 2022 年 1 月春節(jié)前做了 PoC 測(cè)試,在春節(jié)后 3 月份開始搭建正式環(huán)境并安排遷移。為了避免導(dǎo)致業(yè)務(wù)中斷,整個(gè)遷移過程以相對(duì)較慢的節(jié)奏分階段執(zhí)行,截至目前(2022 年 7 月)進(jìn)度約 40%,計(jì)劃在 2022 年內(nèi)完成整體的搬遷。 遷移完后,云上的 EMR 集群數(shù)據(jù)量預(yù)計(jì)會(huì)超過單副本 1 PB.

架構(gòu)設(shè)計(jì)

做完技術(shù)選型之后,架構(gòu)設(shè)計(jì)也能很快確定下來??紤]到除了 Hadoop 上云之外,仍然有大部分業(yè)務(wù)會(huì)繼續(xù)保留在數(shù)據(jù)中心,所以整體實(shí)際上是個(gè)混合云的架構(gòu)。

部署和配置

  • 關(guān)于IDC-阿里云專線:能提供專線服務(wù)的供應(yīng)商很多,包括 IDC、阿里云、運(yùn)營(yíng)商等,選擇的時(shí)候主要考慮線路質(zhì)量、成本、施工周期等因素,最終我們選擇了IDC的方案。IDC 跟阿里云有合作,很快就完成了專線的開通。這方面如果遇到問題,可以找 IDC 和阿里云的支持。除專線租用成本,阿里云也會(huì)收取下行(從阿里云到 IDC)方向傳輸費(fèi)用。專線兩端的內(nèi)網(wǎng) IP 完全互通,阿里云和 IDC 兩側(cè)都需要一些路由配置。
  • 關(guān)于EMR Core/Task 節(jié)點(diǎn)類型的選擇:
  1. JuiceFS 可以使用本地硬盤做緩存,能進(jìn)一步減少 OSS 帶寬需求并提高 EMR 性能。更大的本地存儲(chǔ)空間,可以提供更高的緩存命中率。
  2. 阿里云本地 SSD 實(shí)例是較高性價(jià)比的 SSD 存儲(chǔ)方案(相對(duì)于云盤),用作緩存正合適。
  3. JuiceFS 社區(qū)版未支持分布式緩存,意味著每一個(gè)節(jié)點(diǎn)都需要一個(gè)緩存池,所以應(yīng)該選用盡量大的節(jié)點(diǎn)。

基于以上考慮和配置對(duì)比,我們決定選用 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)估對(duì)比,決定直接使用 EMR 5 的最新版,幾乎所有組件的大版本都做了升級(jí)(包含 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 緩存目錄。這個(gè)參數(shù)支持通配符,對(duì)多個(gè)硬盤的實(shí)例環(huán)境很友好,如設(shè)置為/mnt/disk*/juicefs-cache(需要手動(dòng)創(chuàng)建目錄,或在EMR節(jié)點(diǎn)初始腳本中創(chuàng)建),即用全部本地 SSD 作為緩存。另外也要關(guān)注 juicefs.cache-sizejuicefs.free-space 兩個(gè)參數(shù)。

  • juicefs.push-gateway:設(shè)置一個(gè) Prometheus Push Gateway,用于采集 JuiceFS Java 客戶端的指標(biāo)。

  • juicefs.usersjuicefs.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)過一些測(cè)試,確認(rèn) JuiceFS 可以完美應(yīng)用于 Kafka Connect 的 HDFS Sink 插件(我們把配置方式也補(bǔ)充到了官方文檔)。相比使用 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

請(qǐng)參見 JuiceFS Java SDK 的配置文檔。

  • Kafka Connector 任務(wù)設(shè)置:
hadoop.conf.dir=<core-site.xml所在目錄>

store.url=jfs://<JuiceFS文件系統(tǒng)名稱>/<路徑>

PoC

PoC 的目的是快速驗(yàn)證方案的可行性,有幾個(gè)具體目標(biāo):

  • 驗(yàn)證 EMR + JuiceFS + OSS 整體方案的可行性
  • 檢查 Hive、Impala、Spark、Ranger 等組件版本的兼容性
  • 評(píng)估對(duì)比性能表現(xiàn),用了 TPC-DS 的測(cè)試用例和部分內(nèi)部真實(shí)業(yè)務(wù)場(chǎng)景,沒有非常精確的對(duì)比,但能滿足業(yè)務(wù)需求
  • 評(píng)估生產(chǎn)環(huán)境所需的節(jié)點(diǎn)實(shí)例類型和數(shù)量(算成本)
  • 探索數(shù)據(jù)同步方案
  • 探索驗(yàn)證集群與自研 ETL 平臺(tái)、Kafka Connect 等的集成方案

期間做了大量測(cè)試、文檔調(diào)研、內(nèi)外部(阿里云 + JuiceFS 團(tuán)隊(duì))討論、源碼理解、工具適配等工作,最終決定繼續(xù)推進(jìn)。

數(shù)據(jù)同步

要遷移的數(shù)據(jù)包括兩部分:Hive Metastore 元數(shù)據(jù)以及 HDFS 上的文件。由于不能中斷業(yè)務(wù),采用存量同步 + 增量同步(雙寫)的方式進(jìn)行遷移;數(shù)據(jù)同步完后需要進(jìn)行一致性校驗(yàn)。

存量同步

對(duì)于存量文件同步,可以使用 JuiceFS 提供的功能完整的數(shù)據(jù)同步工具 sync 子命令 來實(shí)現(xiàn)高效遷移。JuiceFS sync 命令支持單節(jié)點(diǎn)和多機(jī)并發(fā)同步,實(shí)際使用時(shí)發(fā)現(xiàn)單節(jié)點(diǎn)開多線程即可打滿專線帶寬,CPU 和內(nèi)存占用低,性能表現(xiàn)非常不錯(cuò)。

Hive Metastore 的數(shù)據(jù)同步則相對(duì)麻煩些:

  • 兩個(gè) Hive 版本不一致,Metastore 的表結(jié)構(gòu)有差異,因此無法直接使用 MySQL 的導(dǎo)出導(dǎo)入功能
  • 遷移后需要修改庫、表、分區(qū)存儲(chǔ)路徑(即 dbs 表的 DB_LOCATION_URIsds 表的LOCATION

因此我們開發(fā)了一套腳本工具,支持表和分區(qū)粒度的數(shù)據(jù)同步,使用起來很方便。

增量同步

增量數(shù)據(jù)主要來自兩個(gè)場(chǎng)景:Kafka Connect HDFS Sink 和 ETL 程序,我們采用了雙寫機(jī)制。

Kafka Connect 的 Sink 任務(wù)都復(fù)制一份即可,配置方式上文有介紹。ETL 任務(wù)統(tǒng)一在內(nèi)部自研的低代碼平臺(tái)上開發(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)

數(shù)據(jù)同步完后需要進(jìn)行一致性校驗(yàn),分三層:

  • 文件一致。在存量同步階段做校驗(yàn),通常的方式是用 checksum. 最初的 JuiceFS sync 命令不支持 checksum 機(jī)制,我們建議和討論后,JuiceFS 團(tuán)隊(duì)很快就加上了該功能(issue,pull request)。除了 checksum,也可考慮使用文件屬性對(duì)比的方式:確保兩個(gè)文件系統(tǒng)里所有文件的數(shù)量、修改時(shí)間、屬性一致。比 checksum 的可靠性稍弱,但更輕量快捷。
  • 元數(shù)據(jù)一致。有兩種思路:對(duì)比 Metastore 數(shù)據(jù)庫的數(shù)據(jù),或?qū)Ρ?Hive 的 DDL 命令的結(jié)果。
  • 計(jì)算結(jié)果一致。即使用 Hive/Impala/Spark 跑一些查詢,對(duì)比兩邊的結(jié)果是否一致。一些可以參考的查詢:表/分區(qū)的行數(shù)、基于某個(gè)字段的排序結(jié)果、數(shù)值字段的最大/最小/平均值、業(yè)務(wù)中經(jīng)常使用的統(tǒng)計(jì)聚合等。

數(shù)據(jù)校驗(yàn)的功能也封裝到了腳本里,方便快速發(fā)現(xiàn)數(shù)據(jù)問題。

后續(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í)例,爭(zhēng)取能在滿足業(yè)務(wù) SLA 的前提下降低使用成本

一手實(shí)戰(zhàn)經(jīng)驗(yàn)

在整個(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 導(dǎo)致表無法查詢。解決方案是在同步元數(shù)據(jù)時(shí),將 num_nulls=-1 的改成 num_nulls=0. 可能需要用到 CatalogObjects.thrift 文件。
  • 原集群有少量 Textfile 格式的文件用了 snappy 壓縮,新版 Impala 無法讀取,報(bào)錯(cuò) Snappy: RawUncompress failed,可能是 IMPALA-10005 導(dǎo)致的。規(guī)避方案是不要對(duì) Textfile 文件使用 snappy 壓縮。
  • Impala 3.4 相比 2.11 的 CONCAT_WS 函數(shù)行為有差異,老版本 CONCAT_WS('_', 'abc', NULL) 會(huì)返回 NULL,而新版本返回'abc'.
  • Impala 3.4 對(duì) SQL 中的保留關(guān)鍵字引用更嚴(yán)格,必須加上``. 其實(shí)一個(gè)好習(xí)慣是業(yè)務(wù)代碼不要使用保留關(guān)鍵字。
  • PoC 或前期測(cè)試的覆蓋度盡可能完整,用真實(shí)的業(yè)務(wù)代碼去跑。我們?cè)?PoC 和早期遷移的業(yè)務(wù)中用到的組件特性比較少,基本都是最常用、保持兼容的功能,因此比較順利。但在第二批遷移過程中就暴露出了很多問題,雖然最終都有解決,但花了很多額外的時(shí)間去做診斷和定位,打亂了節(jié)奏。

性能

  • EMR 5 的 Impala 3.4 打了 IMPALA-10695 這個(gè)補(bǔ)丁,支持對(duì) 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)的用戶(比較適合新機(jī)器,沒有歷史包袱),或者在 JuiceFS 上維護(hù)一個(gè)用戶映射表。我們之前也分享過一篇 JuiceFS + HDFS 權(quán)限問題定位,有詳細(xì)討論。通常需要維護(hù)映射的用戶有 impala, hive, hadoop 等。如果使用 Confluent Platform 搭建 Kafka Connect,也需要配置 cp-kafka-connect 用戶。
  • 使用默認(rèn)的 JuiceFS IO 配置時(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
  • 注意監(jiān)控 Redis 的空間用量,Redis 如果滿了,整個(gè) JuiceFS 集群無法寫入。
  • 使用 JuiceFS sync 把機(jī)房數(shù)據(jù)往云上同步時(shí),選擇在有 SSD 的機(jī)器上跑,獲得更好的性能。

如有幫助的話歡迎關(guān)注我們項(xiàng)目 Juicedata/JuiceFS 喲! (0?0?)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容