做者:王冬前端
連接:https://www.infoq.cn/article/q58xAGoBIiOImqEEm-A9?utm_source=tuicool&utm_medium=referraljava
隨着移動互聯網的發展,愈來愈多的業務數據和日誌數據須要用戶處理。從而,用數據去驅動和迭代業務發展。數據處理主要包括:計算和查詢。計算主要爲離線計算、實時流計算、圖計算、迭代計算等;查詢主要包括 Ahdoc、OLAP、OLTP、KV、索引等。然而,在數據業務中,咱們時常聽到數據需求方和數據開發方對性能慢的不滿,因此,如何高效響應海量且迫切的數據需求,是大數據平臺須要面對的一個關鍵問題,本文將介紹如何基於 Alluxio 建設分佈式多級緩存系統對數據進行計算加速和查詢加速。c++
對於加速組件,結合生態兼容性和系統成熟性的基礎上,咱們選擇 Alluxio,咱們知道,Alluxio 是經過 UFS 思想訪問底層持久化的分佈式數據。一般,咱們的數據主要存放在公司私有 HDFS 和 MySQL 上。那麼,如何經過 UFS 思想訪問到私有 HDFS 數據進行加速是咱們面對的主要問題。私有 HDFS 因爲歷史緣由,其基於的 HDFS 版本較低,加上公司對 HDFS 進行了部分改造,使得開源的計算和查詢組件訪問公司內部的離線數據較爲困難。所以,如何打通 Alluxio 訪問私有 HDFS 成爲了系統的關鍵,後面的章節中,咱們會作相關介紹。web
總體上,咱們當前的多級緩存系統由私有 HDFS(PB 級別) + MEM(400G) + SSD(64T) 共 3 層組成。 示意以下:面試
系統會根據相似 LRU 思想對熱點數據進行緩存。咱們主要存放熱點部門核心數據。因爲資源申請緣由,咱們的 Alluxio 在南方,UFS 在北方, 因此後面的測試數據均爲跨地域性能數據 ,提供基於 Spark、Hive、 Presto、YARN、API 等方式訪問數據。shell
對於多級分佈式緩存系統,咱們實現的總體示意圖以下:緩存
從上述方案中,咱們能夠看出,若是經過 path 路徑方式訪問私有 HDFS 數據,直接使用 alluxio:// 協議路徑便可;可是,若是要開源的 Hive 或者開源組件 (基於 Hive 橋接) 以數據表方式訪問公司內部的私有 HDFS 數據,須要進行「表 schema 映射」,思路以下圖:網絡
基於上述方案,能夠大體抽象出使用 Alluxio 的幾個通常性步驟,以下:架構
下面,咱們會一一對每一個步驟進行相關說明及案例數據分析。併發
因爲 UFS 隨時可能會有變更,致使 Alluxio Meta 和 UFS 的 Meta 不一致,那麼,如何在 Alluxio 的 master 中同步 UFS 文件的 Meta 十分重要,因爲 Alluxio Meta 的 load 和 sync 性能成本較高(對於 load 和 sync 區別,本文不贅述),官方不推薦過分頻繁 load 和 sync Alluxio 的 Meta 數據。
在咱們的集羣中,咱們均採用了默認的配置,而對於 Aluxio Meta 和 UFS Meta 的狀態主要有如下 3 種:
Meta 同步方式 | 說明 |
---|---|
fs ls path | 查看文件狀態 |
fs checkConsistency -r path | 檢測 Alluxio Meta 和 UFS Meta 的一致性,並進行 repair 修復 |
若是經過上面 2 種方法,Meta 不管如何沒法同步(你們應該會遇到這類狀況),能夠考慮 fs rm -R --alluxioOnly path 從 Alluxio 中刪除數據 (僅刪除 Alluxio 中的數據,不刪除對應 UFS 上的數據),而後再 fs ls path 即可以讓 Alluxio 中的 Meta 和 UFS 的真實 Meta 同步一致。
咱們使用 Alluxio 自帶的 fs ls 命令進行 Meta 同步,相關 Alluxio 設置以下:
複製代碼
alluxio.user.network.netty.timeout=600min alluxio.user.network.netty.writer.close.timeout=600min alluxio.user.network.socket.timeout=600min
上面的設置主要是爲了解決網絡超時,Meta 同步是很是耗時的操做。
數據同步性能數據以下(請忽略分區大小的合理性):
有了緩存系統,那麼,咱們須要提早經常使用數據預加載到緩存系統中,如此,當用戶使用時候,直接從緩存中讀取,加快讀取速度。數據預加載的方式有以下圖的 3 種方式:
加載方式 | 數據類型 | 相關說明 |
---|---|---|
Alluxio load 命令 | path 類型數據 | alluxio 文件系統的基礎 shell 命令 |
Spark JAR | path 類型數據 | 本身開發,基於分佈式加載,利用 yarn 模式的 jar,傳入 path 這個參數,來 count 文件的條數,以達到加載文件的目的。好處在於,能夠經過配置 spark-submit 的相關參數來調整加載的速度 |
SQL 命令 | Hive table 類型數據 | 對於 Hive 表的數據,能夠直接利用 SELECT COUNT(*) FROM T WHERE condition 方式加載。 |
咱們主要利用 Spark RDD count 方式來預加載數據,Spark 任務參數以下:
複製代碼
spark.executor.cores4 spark.executor.instances200 spark.executor.memory20g spark.speculationtrue spark.speculation.interval1000ms spark.speculation.multiplier5 spark.speculation.quantile0.95
能夠注意到上面開啓了比較嚴格的探測執行,由於在實際應用中,咱們常常發現極少個別 part 的 load 很是慢。因此,在嚴格條件下開起探測執行,既保證了計算執行效率,又不太會影響到集羣性能。
本地化數據,相信你們都比較清楚,使用本地數據能夠有效地提到數據讀取效率,具體能夠將每一個 worker 節點的 alluxio.worker.hostname 設置爲對應的 $HOSTNAME,熟悉 Spark 的同窗知道,這個設置相似 Spark 中的 SPARK_LOCAL_HOSTNAME 設置。
上圖中,介詞 through 和 on 的區別是,前者爲首次從 UFS 上加載數據(即直接從私有 HDFS 上讀取數據),後者爲直接從 Alluxio 緩存中讀取數據。
根據 Alluxio 官方介紹,寫數據方式主要有 3 種:
Default write type when creating Alluxio files. Valid options are MUST_CACHE
(write will only go to Alluxio and must be stored in Alluxio), CACHE_THROUGH
(try to cache, write to UnderFS synchronously), THROUGH
(no cache, write to UnderFS synchronously).
本文僅測試 CACHE_THROUGH, 數據爲 150G,8000 個 part,因爲性能不佳,推測主要因爲 Meta 同步致使,因此後放棄此方法,因爲任務結算結果數據一般不大, 改用 MUST_CACHE 或者直寫 HDFS。
當結果數據無需緩存到 Alluxio 時,咱們一樣能夠選擇直接將數據寫入到 HDFS,此方案也無需進行 Alluxio 和 UFS 以前的 Meta 同步。
因爲公司內部的私有 HDFS 系統和開源最新版本的 HADOOP 生態難以直接融合,有些接口不支持,因而想到辦法就是增長 1 個 UFS 存儲支持。借鑑公司 Spark 對於私有 HDFS 訪問思路,基於公司基礎部門訪問私有 HDFS 的動態庫及 JNI 的思想,實現對私有 HDFS 的打通。
關於 libstdc++.so.6 和 libc.so.6 的關係,本文不贅述。因爲咱們增長的 UFS 是利用 java 經過 jni 調用 so 庫,而使用的 so 文件依賴的 libstdc++.so.6 版本較高,提示錯誤以下:
複製代碼
java.lang.UnsatisfiedLinkError:/tmp/libxxx5420953064508929748.so:/usr/lib64/libstdc++.so.6:version`GLIBCXX_3.4.15' not found
或者
複製代碼
glibc/libc.so.6:version`GLIBC_2.14' not found (requiredby/usr/lib64/libstdc++.so.6)
可利用如:strings /usr/lib64/libstdc++.so.6 | grep "GLIB" 查看 libstdc++.so.6 和 libc.so.6 的符號庫版本。
其本質緣由主要是,由於咱們環境使用的 java 目錄內部的 so 庫依賴的 libstdc++.so.6 的路徑有問題,可經過命令 scanelf -F "%F %r" -BR $JAVA_HOME
中的 so 對於 libstdc++.so.6 的搜索路徑,一樣也能夠利用命令 patchelf --set-interpreter
和 patchelf --force-rpath --set-rpath
去修改優先搜索路徑。
在測試連通公司私有 HDFS 集羣的過程當中,咱們遇到了一個表現個比較奇怪的問題,就是啓動 master 後,Alluxio 前端 web 頁面菜單 "Browse" 點擊無響應,debug 代碼發現,某個 reentrantLock 的讀計數沒有正確降爲 0(Master 啓動過程當中出現,因此 debug 時候須要設置 suspend=y,同時可從 AlluxioMaster 的 main 函數開始入手),致使一直處於死鎖狀態,這個問題排查了好久,近乎把 Alluxio 啓動代碼邏輯都看完了,代碼上沒有發現問題,後來無心發現是由於各節點(master 和 workers)上沒有安裝 Agent,由於前文提到 JNI 使用的 so 庫須要經過相似代理的方式先訪問 Agent, 利用本地的 Agent 去訪問私有 HDFS。
因爲私有 HDFS 和和最新 HDFS 的差別,不存在 recoverLease, 這個函數主要在 XXXUnderFileSystem.java 中,主要用戶當 Alluxio 的 journal 文件非正常關閉下進行恢復。目前,因爲時間比較緊,這個功能暫時被跳過。
相關機器配置和組件版本以下:
複製代碼
CPU56core、MEM192G、SSD1.6T、Disk XT CentOS6.3 Alluxio1.8 hadoop-2.6.0-cdh5.14.0 spark-2.3.2-bin-hadoop2.7
Alluxio 集羣使用 alluxio 用戶建立,便於遷移及維護。若是是 root 帳戶部署,可能會減小很多權限問題,可是和 root 帳號耦合度過高。因此,不推薦直接用 root 帳號安裝 Alluxio。
Alluxio 啓動 (bin/alluxio-start.sh)、關閉 (bin/alluxio-top.sh) 等腳本中的日誌顯示不夠友好,都是用 echo 方式顯示,它的啓動關閉日誌沒有日期,對於新手來講,安裝部署問題不少,而日誌又沒有時間,形成沒法區分日誌對應哪次操做,形成效率低下。
目前的./bin/alluxio-start.sh [workers|master|all] [NoMount|SudoMount],它會默認不給任何提示,先殺死進程後再啓動進程,並且不是相似 hadoop,提示進程運行中,須要先人肉殺死再啓動,咱們進行了改造。否則,對於緩存在內存中的數據丟失。
爲了保證速度,咱們可能設置 MEM 做爲一級緩存以下
複製代碼
alluxio.worker.tieredstore.level0.alias=MEM alluxio.worker.tieredstore.level0.dirs.path=/mnt/ramdisk alluxio.worker.tieredstore.level0.dirs.quota=${alluxio.worker.memory.size} alluxio.worker.tieredstore.level0.reserved.ratio=0.1
那麼在執行./bin/start-alluxio.sh workers SudoMount 時會提示出錯,由於申請內存申請沒有權限,解決方案,能夠在 /etc/sudoers 文件中增長一行: alluxio ALL=(ALL) ALL
本文中的多級緩存系統(BigCache)除了能夠加速訪問熱數據外,還變相起到了橋接做用。
讓本來沒法直接訪問公司存儲系統數據的新生代開源計算查詢組件,能夠經過訪問 alluxio 協議變相訪問私有 HDFS 數據,從 0 到 1 開啓了訪問公司私有 HDFS 數據的可能!
另外,多級緩存系統不但在離線數據加工方面能有效加速,同時它亦可在對象存儲系統中獲得較好的應用潛力。
如上面第 3 章節提到,如今咱們若是要讓一些開源組件(基於 Hive 訪問數據)訪問到公司內部 Hive(私有 HDFS) 的數據,咱們須要人工建設表的 schema 進行映射,而後利用腳本進行表的 partition 加載,這一類通用工做,後續計劃 web 化、自動化。
這個問題在整個新增 UFS 模塊開發中,耽誤了很是多的時間,主要緣由是由於咱們底層是經過 JNI 利用公司基礎部門的.so 動態庫訪問公司底層的私有 HDFS,在咱們配置了 HA 後,重啓過程當中,會出現 core dump,參考了公司相關 wiki,定位成本比較高,因此後續須要對 core 的問題進行進一步排查,支持系統的 HA。
近年來,公司物理機器的配置愈來愈好,不少機器上都配置有 SSD 硬盤,而不少線上服務可能只用到了 HD 部分,對 SSD 的需求不大,因此若是可以經過混部的方式,將各臺機器的 SSD 利用起來,造成一個巨大的多級緩存池,用來加速離線數據計算和查詢,帶來時效提升收益的同時,也大大提升了機器的利用率,下降成本。
如上文一些章節提到,目前易用性還須要進一步提升,好比對於 In Alluxio Data 的搜索,某些數據緩存過時時間的設置,集羣的維護等等都較爲不便,同時,對於 Meta 同步、數據加載、數據讀取等性能提升也有較大需求。
若是對Java、微服務、分佈式、高併發、高可用、大型互聯網架構技術、面試經驗交流感興趣的。
能夠加我架構圈子羣:834-962-734 領取資料,羣內天天更新資料,免費領取。