Alluxio在多級分散式快取系統中的應用

weixin_33766168發表於2019-01-28

1. 前言

隨著移動網際網路的發展,越來越多的業務資料和日誌資料需要使用者處理。從而,用資料去驅動和迭代業務發展。資料處理主要包括:計算和查詢。計算主要為離線計算、實時流計算、圖計算、迭代計算等;查詢主要包括Ahdoc、OLAP、OLTP、KV、索引等。然而,在資料業務中,我們時常聽到資料需求方和資料開發方對效能慢的不滿,所以,如何高效響應海量且迫切的資料需求,是大資料平臺需要面對的一個關鍵問題,本文將介紹如何基於Alluxio建設分散式多級快取系統對資料進行計算加速和查詢加速。

2. 離線資料計算查詢加速問題

對於加速元件,結合生態相容性和系統成熟性的基礎上,我們選擇Alluxio,我們知道,Alluxio是通過UFS思想訪問底層持久化的分散式資料。通常,我們的資料主要存放在公司私有HDFS和MySQL上。那麼,如何通過UFS思想訪問到私有HDFS資料進行加速是我們面對的主要問題。私有HDFS由於歷史原因,其基於的HDFS版本較低,加上公司對HDFS進行了部分改造,使得開源的計算和查詢元件訪問公司內部的離線資料較為困難。因此,如何打通Alluxio訪問私有HDFS成為了系統的關鍵,後面的章節中,我們會做相關介紹。

3. 基於Alluxio的解決方案

整體上,我們當前的多級快取系統由私有HDFS(PB級別) + MEM(400G) + SSD(64T)共3層組成。 示意如下:

\"image\"

系統會根據類似LRU思想對熱點資料進行快取。我們主要存放熱點部門核心資料。由於資源申請原因,我們的Alluxio在南方,UFS在北方,所以後面的測試資料均為跨地域效能資料,提供基於Spark、Hive、 Presto、YARN、API等方式訪問資料。

對於多級分散式快取系統,我們實現的整體示意圖如下:

\"image\"

從上述方案中,我們可以看出,如果通過path路徑方式訪問私有HDFS資料,直接使用alluxio://協議路徑即可;但是,如果要開源的Hive或者開源元件(基於Hive橋接)以資料表方式訪問公司內部的私有HDFS資料,需要進行“表schema對映”,思路如下圖:

\"image\"

基於上述方案,可以大致抽象出使用Alluxio的幾個一般性步驟,如下:

\"image\"

下面,我們會一一對每個步驟進行相關說明及案例資料分析。

3.1 Alluxio Meta資料同步(load和sync)

由於UFS隨時可能會有變動,導致Alluxio Meta和UFS的Meta不一致,那麼,如何在Alluxio的master中同步UFS檔案的Meta十分重要,由於Alluxio Meta的load和sync效能成本較高(對於load和sync區別,本文不贅述),官方不推薦過度頻繁load和sync Alluxio的Meta資料。

3.1.1 同步方案

在我們的叢集中,我們均採用了預設的配置,而對於Aluxio Meta和UFS Meta的狀態主要有以下3種:

\"image\"

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同步一致。

3.1.2 Meta同步效能

我們使用Alluxio自帶的fs ls命令進行Meta同步,相關Alluxio設定如下:

alluxio.user.network.netty.timeout=600minalluxio.user.network.netty.writer.close.timeout=600minalluxio.user.network.socket.timeout=600min

上面的設定主要是為了解決網路超時,Meta同步是非常耗時的操作。

資料同步效能資料如下(請忽略分割槽大小的合理性):

\"image\"

3.2 Alluxio載入資料

3.2.1 資料載入方案

有了快取系統,那麼,我們需要提前常用資料預載入到快取系統中,如此,當使用者使用時候,直接從快取中讀取,加快讀取速度。資料預載入的方式有如下圖的3種方式:

\"image\"

載入方式資料型別相關說明
Alluxio load命令path型別資料alluxio檔案系統的基礎shell命令
Spark JARpath型別資料自己開發,基於分散式載入,利用yarn模式的jar,傳入path這個引數,來count檔案的條數,以達到載入檔案的目的。好處在於,可以通過配置spark-submit的相關引數來調整載入的速度
SQL命令Hive table型別資料對於Hive表的資料,可以直接利用SELECT COUNT(*) FROM T WHERE condition方式載入。

3.2.2 資料載入效能

我們主要利用Spark RDD count方式來預載入資料,Spark任務引數如下:

spark.executor.cores 4spark.executor.instances 200spark.executor.memory 20gspark.speculation truespark.speculation.interval 1000msspark.speculation.multiplier 5spark.speculation.quantile 0.95 

可以注意到上面開啟了比較嚴格的探測執行,因為在實際應用中,我們經常發現極少個別part的load非常慢。所以,在嚴格條件下開起探測執行,既保證了計算執行效率,又不太會影響到叢集效能。

\"image\"

3.3 Alluxio資料的讀取

3.3.1 資料本地化

本地化資料,相信大家都比較清楚,使用本地資料可以有效地提到資料讀取效率,具體可以將每個worker節點的alluxio.worker.hostname設定為對應的$HOSTNAME,熟悉Spark的同學知道,這個設定類似Spark中的SPARK_LOCAL_HOSTNAME設定。

3.3.2 讀取效能資料1(私有HDFS-\u0026gt;Alluxio-\u0026gt;Hive/Presto)

\"image\"

上圖中,介詞through和on的區別是,前者為首次從UFS上載入資料(即直接從私有HDFS上讀取資料),後者為直接從Alluxio快取中讀取資料。

3.3.3 讀取效能資料2(私有HDFS-\u0026gt;Alluxio-\u0026gt;Hive-\u0026gt;Cube)

\"image\"

3.3.4 讀取效能資料3(私有HDFS-\u0026gt;Alluxio-\u0026gt;Spark)

\"image\"

3.4 寫入資料效能

3.4.1 通過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。

3.4.2 通過hdfs://直接寫入

當結果資料無需快取到Alluxio時,我們同樣可以選擇直接將資料寫入到HDFS,此方案也無需進行Alluxio和UFS之前的Meta同步。

4 Alluxio叢集建設

4.1 打通私有HDFS

4.1.1 增加模組

由於公司內部的私有HDFS系統和開源最新版本的HADOOP生態難以直接融合,有些介面不支援,於是想到辦法就是增加1個UFS儲存支援。借鑑公司Spark對於私有HDFS訪問思路,基於公司基礎部門訪問私有HDFS的動態庫及JNI的思想,實現對私有HDFS的打通。

4.1.2 遇到的libstdc++.so.6及libc.so.6版本過低問題

關於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 (required by /usr/lib64/libstdc++.so.6)

可利用如:strings /usr/lib64/libstdc++.so.6 | grep \u0026quot;GLIB\u0026quot;檢視libstdc++.so.6和libc.so.6的符號庫版本。

其本質原因主要是,因為我們環境使用的java目錄內部的so庫依賴的libstdc++.so.6的路徑有問題,可通過命令scanelf -F \u0026quot;%F %r\u0026quot; -BR $JAVA_HOME中的so對於libstdc++.so.6的搜尋路徑,同樣也可以利用命令patchelf --set-interpreterpatchelf --force-rpath --set-rpath去修改優先搜尋路徑。

4.1.3 無法連通的問題

在測試連通公司私有HDFS叢集的過程中,我們遇到了一個表現個比較奇怪的問題,就是啟動master後,Alluxio前端web頁面選單\u0026quot;Browse\u0026quot;點選無響應,debug程式碼發現,某個reentrantLock的讀計數沒有正確降為0(Master啟動過程中出現,所以debug時候需要設定suspend=y,同時可從AlluxioMaster的main函式開始入手),導致一直處於死鎖狀態,這個問題排查了很久,近乎把Alluxio啟動程式碼邏輯都看完了,程式碼上沒有發現問題,後來無意發現是因為各節點(master和workers)上沒有安裝Agent,因為前文提到JNI使用的so庫需要通過類似代理的方式先訪問Agent, 利用本地的Agent去訪問私有HDFS。

4.1.4 recoverLease函式

由於私有HDFS和和最新HDFS的差異,不存在recoverLease, 這個函式主要在XXXUnderFileSystem.java中,主要使用者當Alluxio的journal檔案非正常關閉下進行恢復。目前,由於時間比較緊,這個功能暫時被跳過。

4.2 叢集部署

相關機器配置和元件版本如下:

CPU 56core、MEM 192G、SSD 1.6T、Disk XTCentOS 6.3Alluxio 1.8hadoop-2.6.0-cdh5.14.0spark-2.3.2-bin-hadoop2.7

4.2.1 使用者

Alluxio叢集使用alluxio使用者建立,便於遷移及維護。如果是root賬戶部署,可能會減少不少許可權問題,但是和root賬號耦合度太高。所以,不推薦直接用root賬號安裝Alluxio。

4.2.2 部署常見問題

4.2.2.1 日誌顯示

Alluxio啟動(bin/alluxio-start.sh)、關閉(bin/alluxio-top.sh)等指令碼中的日誌顯示不夠友好,都是用echo方式顯示,它的啟動關閉日誌沒有日期,對於新手來說,安裝部署問題很多,而日誌又沒有時間,造成無法區分日誌對應哪次操作,造成效率低下。

4.2.2.2 叢集啟動

目前的./bin/alluxio-start.sh [workers|master|all] [NoMount|SudoMount],它會預設不給任何提示,先殺死程式後再啟動程式,而且不是類似hadoop,提示程式執行中,需要先人肉殺死再啟動,我們進行了改造。不然,對於快取在記憶體中的資料丟失。

4.2.2.3 RAM記憶體申請

為了保證速度,我們可能設定MEM作為一級快取如下

alluxio.worker.tieredstore.level0.alias=MEMalluxio.worker.tieredstore.level0.dirs.path=/mnt/ramdiskalluxio.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

5 未來計劃

5.1 更多應用場景

本文中的多級快取系統(BigCache)除了可以加速訪問熱資料外,還變相起到了橋接作用。

讓原本無法直接訪問公司儲存系統資料的新生代開源計算查詢元件,可以通過訪問alluxio協議變相訪問私有HDFS資料,從0到1開啟了訪問公司私有HDFS資料的可能!

另外,多級快取系統不但在離線資料加工方面能有效加速,同時它亦可在物件儲存系統中得到較好的應用潛力。

5.2 Hive表對映自動探測更新

如上面第3章節提到,現在我們如果要讓一些開源元件(基於Hive訪問資料)訪問到公司內部Hive(私有HDFS)的資料,我們需要人工建設表的schema進行對映,然後利用指令碼進行表的partition載入,這一類通用工作,後續計劃web化、自動化。

5.3 HA的支援

這個問題在整個新增UFS模組開發中,耽誤了非常多的時間,主要原因是因為我們底層是通過JNI利用公司基礎部門的.so動態庫訪問公司底層的私有HDFS,在我們配置了HA後,重啟過程中,會出現core dump,參考了公司相關wiki,定位成本比較高,所以後續需要對core的問題進行進一步排查,支援系統的HA。

5.4 容器化部署

近年來,公司物理機器的配置越來越好,很多機器上都配置有SSD硬碟,而很多線上服務可能只用到了HD部分,對SSD的需求不大,所以如果能夠通過混部的方式,將各臺機器的SSD利用起來,形成一個巨大的多級快取池,用來加速離線資料計算和查詢,帶來時效提高收益的同時,也大大提高了機器的利用率,降低成本。

5.5 易用性與效能

如上文一些章節提到,目前易用性還需要進一步提高,比如對於In Alluxio Data的搜尋,某些資料快取過期時間的設定,叢集的維護等等都較為不便,同時,對於Meta同步、資料載入、資料讀取等效能提高也有較大需求。

6 參考資料

  1. https://www.alluxio.org/docs/1.8/en/reference/Properties-List.html
  2. https://www.alluxio.org/docs/1.8/en/compute/Hive.html
  3. https://www.alluxio.org/docs/1.8/en/deploy/Running-Alluxio-On-Yarn.html
  4. https://www.alluxio.org/docs/1.8/en/compute/Presto.html
  5. https://www.alluxio.org/docs/1.8/en/compute/Spark.html
  6. https://www.alluxio.org/docs/1.7/en/DevelopingUFSExtensions.html
  7. https://www.alluxio.org/docs/1.8/en/operation/Troubleshooting.html
  8. https://www.alluxio.org/overview/performance-tuning
  9. https://hortonworks.com/blog/resource-localization-in-yarn-deep-dive/

作者介紹

王冬,軟體研發工程師,2012年北京理工大學計算機本碩畢業,從事大資料領域7年多,先後負責大資料元件研發、大資料平臺架構、大資料研發等工作,對大資料整體生態較為熟悉瞭解。

相關文章