大數據公司 LiveRamp 上雲記(四):如何在遷移時處理數百萬請求和 PB 級數據傳輸

複製數據到雲

LiveRamp正在大規模遷移其基礎設施到GCP。在之前的文章中,我們談到了遷移以及使用谷歌作爲雲供應商的決定。在本文中,我想着重強調一個爲完成本次遷移而必須解決的問題:複製我們的數據到雲。

在大數據公司之中,LiveRamp佔據着一個相對小衆的領域:我們所有的產品都與熱數據類的大數據任務相關。我們確實有一些相對較大的歷史數據集,但與我們在線生成和使用的大型數據集相比,這些只是次要問題,我們的數據集預計只能保留幾天。並且由於我們的數據訪問模式,大多數雲數據遷移方案都不適合我們,尤其是像亞馬遜的Snowball或谷歌的設備傳輸,這樣數據傳輸方式對我們毫無用處。

更麻煩的是,保存這些熱數據的託管設施的網絡設備都相當陳舊,它們主要用於數據中心內部的數據傳輸。硬件升級可能會花費數十萬甚至數百萬美元,所以我們不得不利用現有資源,將硬件利用到極致,以獲得50Gbps的GCP(谷歌雲計算平臺)互連吞吐量。我們數據基礎設施團隊的任務是構建工具,從而讓應用程序開發人員能夠共享這些有限的資源,並在不中斷客戶服務的基礎上將數據放入雲中。

Data Replicator

我們所構建的用於滿足這些需求的應用程序稱爲Data Replicator(數據複製器)。本質上,Data Replicator是目前大多數Hadoop版本都支持的DistCp任務的載體,但圍繞它的卻是一些非常複雜的問題,如分佈式作業調度、監控和遵循最小驚喜原則等,我們將在後面詳細討論。

架構

我們使用LiveRamp的daemon_lib項目來編排一組Kubernetes的pod,這些pod來自於一個數據複製請求的提交隊列,每個請求都包含一個源文件路徑和一個目標文件路徑。我們檢查數據源的大小:對於小數據集,我們直接使用本地進程將數據複製到其目的地,而對於大數據集,我們向Hadoop集羣提交一個Hadoop DistCp任務,進而執行高度分佈式的複製(稍後將詳細介紹)。

數據庫作爲優先隊列

像很多應用程序一樣,Data Replicator可以被抽象爲worker從隊列中獲取任務並執行它們。然而,我們並沒有使用現有的一些典型的分佈式隊列解決方案,比如Google的Pub Sub或Apache的Kafka。相反,我們只是使用一些普通的SQL(結構查詢語言)來處理請求。這給了我們一些優勢:

Data Replicator任務可以在任何地方運行30秒到24小時,我們希望儘可能地避免向用戶返回任何類型的失敗(或者請求被刪除等更糟糕的信息)。這意味着我們需要更顯著的持久性和確認特性:只有在工作完成時執行刪除操作,而不是在處理開始時。一個請求的生命週期如下:

大多數分佈式隊列都不能很好地支持一些處理,例如處理可能需要很長時間,或者worker在工作中死亡。如果一個執行者在工作中死亡,請求將被標記爲失敗,並被放到“掛起”隊列或者被手動取消。

同樣,原始請求隊列對長時間請求的狀態的可見性也非常有限。我們希望爲人和軟件客戶端提供一個清晰的系統狀態視圖。因爲這只是SQL,我們可以任意索引從而爲外部應用程序、用戶界面或執行器來提供這種可見性:

具體來說,執行器希望選擇優先級最高的掛起請求。大多數隊列不支持從多達數千計的候選裏獲取一個更高優先級的請求。我們的索引如同一個優先隊列,查詢非常簡潔:

這種細緻的索引可以讓應用程序團隊提交數十萬個低優先級請求,而且不會降級系統的健康狀況:

最後也很重要的是,我們的devops團隊和開發人員對SQL和MySQL都非常瞭解,學習一項新技術並構建與之相關的功能,這也意味着巨大的機會成本。選擇使用SQL,我們能最好地利用開發團隊中現有的人才。

我們使用LiveRamp的daemon_lib項目來編排數據庫檢查流程、將個體標記爲選中、處理它們,然後將它們標記爲完成或失敗。我們利用Apache Curator和Apache ZooKeeper的內置鎖來協調讀取和更新數據庫的進程。我們還使用Curator的臨時鎖來註冊正在完成的工作,這樣,如果數據複製任務由於某種方式死亡,這將會被檢測到,而其它worker會把這項任務返回到隊列中。所有這一切給了我們一個非常有彈性的系統,可以確保我們在正確的時間做正確的事,並且不會有任何損失。

需要澄清的是,我們並沒有爲Data Replicator而構建一個守護服務的基礎設施。daemon_lib和數據庫後端的隊列在LiveRamp內部被廣泛使用,我們也藉助現有的工具快速構建了一個開箱即用的容錯系統。

監控

系統健康的可視化是我們設計服務的驅動目標之一。通過使用LiveRamp的內部服務處理框架,我們得到了一個非常好的用戶界面,該界面顯示了所有Data Replicator請求的彙總:

雖然這提供了系統健康的真實信息,但在LiveRamp我們更喜歡使用DataDog的控制面板來構建時間序列界面,因此我們決定將儘可能多的監控指標推送給DataDog,並在那裏構建一個全面的監控。我們從不同來源獲取數據:

  • 我們以前介紹過MapReduce計數器在調試MapReduce作業時非常有用。Distcp是一個MapReduce任務,因此我們將Distcp的計數器推送給DataDog。
  • 因爲我們的工作隊列很容易查詢,所以我們將掛起的工作隊列也推送給DataDog。
  • 執行者自己推送關於他們正在複製的文件的指標。
  • 我們依靠GCP API來提取雲互連利用率指標

如下是我們構建的一些更常見的參考圖表:

這是一個關於系統健康的最基本的度量標準,顯示了我們工作隊列的大小。如果我們沒有掛起或失敗的請求,那麼就表示我們的狀態非常好。

當然,原始計數只是一個粗略的度量標準。我們支持請求優先級,這樣團隊就可以在不影響高優先級流量的情況下提交大量低優先級冷數據的複製任務。通過跟蹤每個優先級的請求時間,我們可以確認對時間敏感的請求實際上得到了快速處理:

我們最重要的系統限制是帶寬。我們跟蹤了互連帶寬的歷史使用情況:

這提供了聚合利用率,但沒有按應用程序分解。由於單個請求被客戶端應用程序標記,我們實際上可以將帶寬利用率歸於服務消費者:

通過這些工具,我們可以很直觀地瞭解數據複製服務的健康狀況。

DistCp問題

我們在使用DistCp時遇到了一個有趣的接口問題:DistCp的覆寫選項。覆寫標誌位決定了當DistCp檢測到其試圖複製的文件已經在目標文件系統時所發生的情況:如果標誌位爲假,DistCp不復制文件;如果標誌位爲真,它將刪除已經存在的文件並複製源文件。

Distcp不會檢查文件的內容,因此用戶必須知道他們的數據是不是最新的,以及是否需要覆寫。我們希望使用者能夠自己設置這個標誌位,這樣他們就可以在不知道數據集複製情況的前提下仍能夠執行最有效的操作,尤其是在他們被要求去重複複製一些並未改變的數據的時候。

但是我們遇到了一個阻礙,正如DistCp文檔中所描述的,覆寫標誌位實際上改變了被複制數據的目錄結構!我們開始只是打算簡單地把這個信息通知給用戶,並讓他們爲自己的請求負責,但我們認爲這嚴重違背了最小驚喜原則,最終只會給我們的用戶和團隊帶來更多的痛苦,因此我們決定由自己負責,編寫代碼讓Data Replicator的複製行爲表現一致。

這些封裝DistCp不一致的代碼牽扯到了一些分支邏輯,但最終並沒有像我們起初擔心的那樣複雜。真正困難的是如何證實我們想要覆蓋的測試的確表現出了一致的行爲。爲了測試新代碼,我們使用LiveRamp的generative庫編寫了一個單獨的、可擴展的測試,創建了100多個潛在輸入的組合,並確認創建的文件和目錄結構符合我們的預期。我會在以後介紹更多關於使用generative以及基於屬性的測試經驗。

不同規模的任務

爲保持用戶界面的簡潔性,即便是複製不同大小的文件,Data Replicator都必須爲用戶提供相同的API。所以,不論是複製5TB的冷數據還是複製5MB的導入,用戶最終都會使用相同的服務調用。

雖然MapReduce和DistCP非常樂意啓動一個YARN應用程序來處理一個哪怕只是複製5MB數據的請求,但啓動一個YARN應用程序會產生相當高的開銷:如果向ResourceManager(資源管理器)提交一個5MB的複製任務,那麼就會啓動一個ApplicationMaster(程序調度器),以及一個Map任務來執行實際的複製:

爲避免這種不必要的開銷,當請求的輸入文件爲1GB時,我們將任務降低到“本地模式”。在這種模式下,worker直接將數據從源文件系統複製到GCS,而不需要啓動DistCP應用程序:

本地模式在減少系統開銷方面非常成功;事實上,我們有75%的請求完全跳過了DistCP,直接通過這些worker進行復制:

我們遇到的最後一個瓶頸實際上與我們快速啓動任務的能力有關。當從隊列中拖出任務時,worker會在構建請求時將隊列“鎖定”幾秒鐘。在請求數量極大但請求的工作量又很小的情況下,這會成爲吞吐量的瓶頸。我們通過將[狀態,優先級]隊列中執行器的任務分片以及獨立鎖定分片的方式解決了這個問題:

有了這些,我們就能夠處理儘可能多的請求。

Data Replicator的未來

在LiveRamp,我們喜歡編寫代碼,但我們更喜歡在不使用時將它們刪除。雖然我們爲Data Replicator服務感到驕傲,但我們不會永久性的安裝它。我們正在全面遷移到GCP,一旦遷移完成,我們就不會受任何帶寬限制,也就沒有了使用這個服務的必要。

前三篇文章主要討論瞭如何將我們現有的基礎設施過渡到GCP。在下一篇文章中,我們將討論使用GCP最有趣的部分,即使用雲原生技術重構我們的本地系統。

原文鏈接:

https://liveramp.com/engineering/migrating-a-big-data-environment-to-the-cloud-part-4%ef%bb%bf/

相關閱讀:

大數據公司 LiveRamp 上雲記(一):爲什麼選擇 GCP?

大數據公司 LiveRamp 上雲記(二):哪些功能可以直接遷移,哪些需要重新設計?

大數據公司 LiveRamp 上雲記(三):如何在吞吐量有限的情況下處理數據複製

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章