tft每日頭條

 > 科技

 > 如何實現數據庫調優

如何實現數據庫調優

科技 更新时间:2025-01-06 17:32:09

導讀:今天分享的題目是Alluxio元數據和數據的同步,從設計實現和優化的角度進行讨論。主要包括以下幾個方面的内容:

  • Alluxio簡介
  • Alluxio的數據挂載
  • Alluxio和底層存儲的一緻性
  • Alluxio和UFS的元數據/數據同步
  • 元數據同步的實現原理和優化
  • 對不同場景的推薦配置

01

Alluxio簡介

Alluxio是雲原生的數據編排平台,通過解耦計算和存儲層,在中間産生了一個數據編排層,負責對上層計算應用隐藏底層的時間細節。Alluxio提供了統一的存儲命名空間,在中間層提供了緩存和其他數據管理功能。在下圖可以看到有Spark、Hive、Map reduce這一類傳統的Hadoop大數據計算應用、Presto 這種OLAP類型的數據分析,還有像Tensorflow、Pytorch這樣的AI應用。存儲層比較豐富,包括各種各樣的存儲。

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)1

圖1 Alluxio簡介

下面是Alluxio用戶列表,這些公司都公開展示了Alluxio的使用場景。通過粗略分類,看到非常多的行業,包括互聯網、金融、電子商務、娛樂、電信等。感興趣的同學可以關注公衆号,上面有相關文章的彙總。

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)2

圖2 Alluxio的用戶展示

--

02

Alluxio數據挂載

這部分将首先回顧Alluxio如何通過數據挂載實現統一編排層;之後讨論Alluxio如何和底層存儲保持一緻;介紹元數據和數據同步功能;Alluxio的時間原理和優化;最後對不同場景的推薦配置給出建議。

1. Alluxio統一的數據命名空間

首先介紹數據挂載這個功能。Alluxio通過把底層存儲挂載到Alluxio層上,實現了統一的數據命名空間。

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)3

圖3 Alluxio統一命名空間

上圖的例子中Alluxio挂載了HDFS和對象存儲。Alluxio的文件系統樹就是由左右兩棵樹合成,形成了一個虛拟文件系統的文件系統樹。它可以支持非常多的底層存儲系統,統一把它們稱作Under File System。稱為Under是因為它們都處于Alluxio的抽象層下。Alluxio支持各種各樣不同的底層存儲系統,比如不同版本的HDFS,支持NFS, Ceph, Amazon S3, Google Cloud之類不同的對象存儲。除此之外還支持非常多其他類型的對象存儲,比如微軟Azure、阿裡、華為、騰訊,也包括國内其他供應商,如七牛對象存儲。左下圖中的例子是在自己的電腦上運行Alluxio,可以挂載不同的存儲,比如挂載HDFS,另外還可以挂載不同版本的HDFS,挂載對象存儲,挂載網盤。

2. Alluxio挂載點

Alluxio的統一命名空間,實際就是把挂載合成了一個Alluxio的虛拟層。Alluxio的挂載點可以粗略分成兩種:

  • 根挂載點
  • 嵌套挂載點

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)4

圖4 Alluxio挂載點

根挂載點直接挂在根節點上,組成了Alluxio的根節點。如果沒有根節點,無法産生,繼續形成下面的結構。所以要求在配置文件裡面定義根挂載點,系統啟動的時候就進行挂載,不挂載就沒有辦法啟動。

嵌套挂載點比較靈活,可以通過指令進行挂載。通過這個命令行,發出通知,做挂載的操作。同樣地,可以挂載,也可以卸載,就是把Mount換成Unmount。嵌套挂載點是嵌套在目錄的下面,可以挂在某個部分下面,不一定挂載在根節點下面。這裡有個要求,即兩個嵌套點的樹不能互相覆蓋,這樣帶來的好處是比較靈活。如果根挂載點将來需要更換,為了避免需要改配置和重啟服務,可以使用一個dummy的根挂載點,比如就挂載在本地路徑下面,不使用它,且不在它下面創建任何文件,它存在的唯一目的就是可以啟動Alluxio服務。然後在此基礎上,把所有要管理的存儲,都以嵌套挂載點的方式挂載上去。之後如果要改變,就直接卸載更換為其它挂載點,這樣就很靈活。所有挂載和挂載操作,都會記錄在日志裡,重啟系統,并重啟服務之後,無需再手動操作。

3. Alluxio策略化數據管理

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)5

圖5 Alluxio策略化數據管理

挂載操作有一個進階版操作,目前隻包含在商業版本裡面。所做的事情就是讓用戶可以把兩個存儲挂載到同一個路徑下,可以互相覆蓋。同時通過配置讀寫策略,定義讀寫文件到哪個存儲裡,并給出操作的先後順序。同時Alluxio有一個遷移策略,讓文件可以自動在Alluxio的管理下,在多個存儲之間進行遷移。例如,把HDFS和對象存儲同時挂載到同一路徑下,上層用戶隻能看到這樣一棵樹,但是實際上背後有兩個不同的存儲。通過配置,讓Alluxio把HDFS的數據,根據一些規則,定期遷移進S3,例如規定将超過七天的數據,認定是不常用到的冷數據之後,把它從HDFS的集群拿出來,遷移到S3,節省HDFS的存儲空間。

--

03

Alluxio底層存儲一緻性

在把底層存儲挂載到Alluxio的統一命名空間上之後,如何保持Alluxio和底層存儲的一緻性?我們在這一部分進行分析。

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)6

圖6 Alluxio與一緻性

Alluxio和底層存儲的一緻性,要從Alluxio命名空間中文件的來源說起。文件的操作分為兩類:

  • 一類是寫,上層應用通過Alluxio創建一個文件,通過Alluxio寫入UFS;
  • 一類是讀,上層應用通過Alluxio讀一個文件,當發現自己沒有這個文件的時候,Alluxio從UFS進行加載。

一緻性可以分為兩個部分:

  • Alluxio UFS元數據的一緻性
  • Alluxio UFS數據的一緻性

下面先看寫數據的一緻性。

1. Alluxio寫文件流程

首先Alluxio寫文件的流程可以把它抽象成兩步。第一步是客戶端到Alluxio,第二步是Alluxio到UFS。

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)7

圖7 Alluxio寫文件流程

其中的每一步都可以抽象成下面的三個步驟:

  • 創建文件
  • 寫數據
  • 提交文件

同樣Alluxio到存儲系統也可以同樣地抽象提取。

客戶端和Alluxio之間,主要流程分三步:

  • 客戶端向發請求創建一個文件;
  • 找到Alluxio Worker寫具體對應的數據;
  • 在寫完數據之後,提交這個文件。

同樣Alluxio到存儲系統也抽象成三步。不同存儲系統的抽象和具備的一緻性,都不同,此處進行抽象隻是為了便于理解。比如要求強一緻性保證,但是很多對象存儲,給的一緻性保證會弱很多,比如寫進去之後不能馬上讀到這個數據。在這裡,不考慮這種本身的不一緻性的問題。假設Alluxio向存儲提交了之後,就能保證存儲端的文件就是需要的樣子。

Alluxio為了滿足不同的需求,設計了幾種不同的寫策略,下面逐一分析寫策略的流程以及帶來的數據一緻性保證。

2. Must-Catch寫模式

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)8

圖8 Alluxio:MUST_CACHE寫模式

首先是常用的MUST_CACHE模式。在這種模式下,隻會寫Alluxio緩存不寫UFS。這個模式分為三步:

首先客戶端會向Alluxio 發出創建文件請求,創建的文件隻是一個空文件,作為一個占位;

之後Alluxio Worker實現具體數據的寫操作,具體數據會被分割成多個數據塊,作為Block存在于Alluxio Storage裡面。

在緩存寫之後,客戶端對Master做提交文件的請求,告訴Master寫了這些數據塊,寫到Worker,然後更新對應的元數據,也知道了這些數據塊和Worker所對應的位置。

在這樣的流程之後,Alluxio不會向UFS創建這個文件,也不會寫這個文件,所以Alluxio和UFS之間的元數據和數據都不一緻。

3. Through寫模式

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)9

圖9 Alluxio:Through寫模式

THROUGH的寫模式有所不同,這裡同樣的 createfile() 發出一個請求,然後找Worker寫數據。Worker會做三件事:

  • 創建文件
  • 寫文件
  • 提交文件

在第二步結束後,客戶端會向Alluxio 提交這個文件。因為Alluxio 的提交是發生在文件寫完了之後,所以,Alluxio和UFS此時的元數據是一緻的。因為沒有數據緩存,所以也不存在數據一緻性的問題。

Alluxio的緩存是在需要讀之後才會産生,而這種THROUGH模式是比較适合用來寫已知不再會被Alluxio讀取的數據。所以在這種情況下,元數據是一緻的,也不存在數據不一緻的問題。

4. CACHE_THROUGH寫模式

下面的CACHE_THROUGH模式就是前面兩種模式的結合。

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)10

圖10 Alluxio:CATCH_THROUGH寫模式

唯一的不同點是在第二步,寫緩存的同時又寫了UFS。在這兩個都成功之後,第二步才會成功,之後客戶端才會做提交操作。同樣的道理,因為Alluxio在UFS更新之後才更新,所以兩者的元數據和數據都是一緻的。

5. ASYNC_THROUGH寫模式

最後是ASYNC_THROUGH異步寫模式,和前面的模式唯一的區别是第二步中的UFS寫變成了異步,放在了第四步。

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)11

圖11 Alluxio:ASYNC_THROUGH寫模式

在Alluxio寫緩存之後,首先創建了文件之後,在第二步寫了Alluxio緩存;在第二步緩存寫完之後,Worker就向客戶端返回成功;然後由客戶端向Master提交文件。注意在這個時候,Worker還沒有去UFS創建這個文件,也沒有向UFS寫文件。在Alluxio向客戶端返回請求成功之後,在之後的某個時間,由Job Service把這個文件創建到時裡面,并且持久化。

需要注意:在異步的模式下,持久化由于某些原因失敗了,比如Alluxio成功之後,突然有人直接向裡面創建了一個同名的文件,在第四步的時候,由于緩存和之間産生了不一緻,導緻這個文件無法創建、無法寫入。這個時候,Alluxio會有不一緻的問題,此時需要人工介入來解決這個沖突。

6. 讀文件流程

前文介紹以上四種不同的寫模式以及一緻性保證,現在來看Alluxio的讀文件流程。讀文件也可以粗略分成兩種:冷讀和熱讀。

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)12

圖12 Alluxio:讀文件流程

簡單來說,冷讀情況下Alluxio不知道這個文件,需要從加載元數據和數據。熱讀的時候,緩存命中,不需要加載元數據和數據。

① 冷讀文件

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)13

圖13 Alluxio:冷讀文件

在冷讀流程裡,客戶端向Alluxio請求元數據,此時Master還沒有這個元數據,所以會向UFS發出一個請求,并從UFS加載這個元數據,這也稱之為元數據同步。

在客戶端具體讀數據的時候,客戶端找到Worker,Worker此時還沒有緩存,于是Worker會向UFS做緩存的加載,這就是常說的緩存冷讀。在做完這兩個步驟之後,緩存是和元數據一緻的。

② 熱讀文件

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)14

圖14 Alluxio:熱讀文件

在熱讀的情況下,元數據可以在緩存裡面找到,數據可以在Worker裡面找到;此時不會有對UFS的讀請求。

在緩存命中的時候,如何保證緩存與和是一緻的?這裡包括元數據的一緻和數據的一緻。這個簡單的來說,就是通過Alluxio的元數據和數據的同步機制,也就是下一部分的内容。

--

04

Alluxio和UFS元數據和數據同步

1. 檢查Alluxio元數據/數據一緻性

首先考慮這個問題:在什麼時候需要檢查Alluxio的元數據和數據的一緻性?

首先在寫數據的時候需要檢查。如果這個文件在已經存在了,作為緩存,除了放棄這個操作之外,也沒有其他的選項。因為不能在用戶不知情的情況下,覆蓋掉用戶在裡面的數據。

在讀數據的時候,同樣需要考慮如果文件在裡面已經更新了,那緩存也需要對應進行更新,需要UFS考慮裡面的文件是否發生了變化。

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)15

圖15 檢查Alluxio:元數據/數據一緻性

2. 保證Alluxio元數據/數據一緻性

元數據和數據的一緻性分成兩步來逐個讨論。首先讨論如何保證Alluxio元數據和一緻。Alluxio通過兩種方式來保證:

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)16

圖16 保證Alluxio:元數據/數據一緻性

① 通過基于時間的假設

第一種是通過基于時間的假設,在裡面的文件,在一段時間内它是不變的。判斷方法是在每一次文件源信息、元數據請求的時候,檢查Alluxio的元數據是否足夠新。

這個判斷分成了兩個不同的部分:

  • 在每一次請求的時候
  • 檢查這個元數據是否足夠新

這種元數據的同步機制是惰性的,隻有在請求的時候才會進行檢查。這樣設計的理念是盡量避免訪問慢的操作、昂貴的操作。這樣的事情越少越好、越懶越好。如果Alluxio所知的文件信息足夠新,就假設Alluxio和UFS是一緻的。如果不夠新,就放棄這個假設再做一次同步;同時更新Alluxio裡面的元數據。

② 基于通知

另外一個思路就是抛棄基于時間的假設,基于通知,依賴文件更改的告知。這個不是假設,是一個确定的信息。如果沒有通知文件有變化,就确定Alluxio和現在的文件是一緻的。

其次是如何保證Alluxio和UFS的數據保持一緻。思路也非常簡單:保持數據的一緻,隻需要确定元數據及是否一緻。這裡做出的假設是:如果UFS的數據,文件内容有所改變,那這個改變一定會反映在文件的元數據上。要麼是文件的長度改變,要麼是這個文件的Hash,也就是哈希值會發生改變。通過觀察這個Alluxio和的元數據,可以發現這些變化點。

如果基于這個假設,Alluxio的元數據和UFS保持一緻時緩存和UFS也會一緻。如果觀察元數據發現内容有變化,那麼就更新元數據并抛棄已有緩存。在下一次讀的時候,重新加載緩存。如果發現文件的内容沒有變化,隻做必要的元數據更新,不抛棄數據緩存。

3. 數據同步機制

Alluxio提供兩種同步機制,這裡先介紹時間戳機制,再介紹基于消息的同步機制。

① 基于元數據時間戳的同步機制

下面先看一下第一種機制,基于元數據時間戳的同步機制。

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)17

圖17 基于元數據時間戳同步

時間戳主要是通過配置項alluxio.user.file.metadata.sync.interval,通常稱之為sync.interval或者interval。比較同步數據上次同步的時間戳和配置項。配置項中有幾種不同的配置方式:

  • 配置為-1,就隻在第一次加載的時候進行同步,之後就永遠不再和這個底層存儲去做同步了;
  • 配置為0,每一次訪問的時候,都會進行同步,抛棄所有知識,不做任何假設。
  • 比較常用的一種是用戶指定一個配置值,做一個假設,如果上一次同步的時間還沒有超出這個時間,就假設原信息是新的。這個假設是基于對這個文件的了解,比如:知道文件的來源,知道文件由哪些業務流程産生的。在此基礎上,可以做一個合理的推斷:隻需每隔照一段時間去檢查的就足夠。如何進行配置,請看下圖。

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)18

圖18 元數據同步的開銷

  • 這張圖展示了不同的配置方式帶來什麼樣的行為。這張圖的縱軸是一個RPC完成所需時間。不同的環境、不同測試方式都會得到不一樣的結果。主要看相互之間的大小關系。如果把interval設成零,就是每一次都同步,那每一個RPC都會有元數據同步的開銷,延遲會比較高;
  • 如果interval設為-1,完全關掉同步,隻要文件存在于Alluxio裡面,完成第一次加載,之後的每一次,RPC都會有一個低的延遲,因為沒有做的同步操作。
  • 最常用的是設置成一個适中的值,實際上帶來這樣一個結果,就是如果還在interval之内,RPC能得到快速的返回;如果達到了interval,觸發一次同步,那在下一次RPC就會有一個比較高的開銷。通過這樣的方式,實際上把這個元數據同步的開銷,平均到每一次的RPC請求中。這也大家比較喜歡的方式,因為取得了一個平衡。

② 同步時間間隔配置

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)19

圖19 同步時間間隔配置

這個時間間隔具體配置有三個,優先級是由低到高,後面的配置可以覆蓋前面的配置。

  • 第一種最基礎是配置文件/環境變量方式,是最不靈活的方式。因為整個集群裡面文件都不同,假設也不同,很難使用同樣間隔,所以一般都給一個默認值。
  • 第二種方式是基于路徑的設置做配置。比如:通過管理員指令給這個Alluxio的/data_center1路徑,添加property也就是sync.interval。意思就是假設來自數據中心這個路徑下的所有文件夾下面所有路徑,都按照一個小時一次的時間間隔,在超過一個小時之後,才去再進行一次原文件的同步。這樣的假設的根源就是:知道來自數據中心的文件,它的更新不是特别頻繁,那可以做出這樣的一個判斷。
  • 第三種方式是直接寫在指令裡面。ls是大家最常用的命令。比如:對/data/tables下面的文件做ls操作的時候,給予一個大于零的值。意思就是:如果因為不小心誤操作或者多做了幾次ls,不小心多敲了幾次回車或者腳本寫錯,至少還有一個回旋的餘地,不會一下子觸發大量元數據同步的操作。

Alluxio還提供一些語法糖指令,比如:loadMetadata指令就是專門為了觸發元數據同步。如果加上-F選項,實際上的意思就是把sync.interval設成0,相當于強制進行一次元數據的刷新。ls和metadata這兩個指令的區别:ls把文件展示在面前,ls的RPC有網絡開銷, 會把信息發給你,客戶端要保存下來,并且展示出來。這個不是每一次都需要,假如隻是想要觸發一次元數據的同步,隻需loadMetadata就可以,返回值隻有成功或者失敗,可以節約很多網絡帶寬和的内存開銷。

③ 基于消息的同步機制

以上是基于時間的同步機制,下面看一下另外一種思路,就是基于消息同步機制。

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)20

圖20 基于消息同步

首先需要Alluxio 2.0版本以上,以及Hadoop 2.6.1版本以上,因為HDFS底層的inotify機制是在2.6版本加進去的。實際上發生的就是從HDFS的namenode直接讀取HDFS有哪些文件發生了變化。實現原理就是維護了一個Alluxio和namenode之間通過HDFS的inotify機制保持了一個信息流。Alluxio定期心跳從這個信息流裡面去讀,有哪些文件發生了變化,然後根據這個變化的具體的類型,Alluxio決定要不要再去namenode觸發一次元數據的同步。

這樣的元數據同步是有的放矢,不再是基于時間猜測。每一次同步都是有理有據,知道文件已經改變,稱為Active Sync,也是因為在這裡化被動為主動,不再被動去猜,而是主動知道了有哪些變化,然後主動去觸發同步。但是這個inotify隻能告訴告訴我們哪些文件發生了變化以及變化是什麼類型,包含的信息很少,具體要做同步還需要一個元數據同步的機制,所以這一步是繞不開的。具體的使用也非常簡單,可以通過指令來開啟它,也可以關閉,或者查看現在有哪些HDFS路徑或挂載點開啟了這個功能,這些指令也受Journal日志保護,當開啟了Active Sync功能之後,就會被記錄在Journal日志裡面,在重啟集群之後,無需重敲一遍指令。

4. Active Sync性能取舍

Active Sync也不是萬能藥,它做了一些功能的取舍。每種設計都有它的取舍,因此也有适合和不适合的場景。

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)21

圖21 Active Sync性能取舍

Active Sync在确定了文件更改之後,再去做同步操作,它省掉了那些沒有變化、無用的同步操作。但是每一個文件的更改,都會觸發同步操作。具體文件的更改并不一定是客戶端的請求,雖然是主動加載它,但實際上并不一定用到,有可能是多餘的操作。

Active Sync和基于時間戳的同步機制,各有利弊。具體選擇時需要進行考量,在後面的章節會總結分析哪種場景适合的配置。同時要注意Active Sync隻支持HDFS,原因是隻有HDFS提供API,其他存儲沒有機制可以知道有哪些文件發生了變化,所以沒有辦法來實現。

--

05

元數據同步實現與優化

在了解了機制後,現在了解一下元數據同步的實現原理,然後再看元數據同步的優化。

1. 元數據同步原理

目前元數據的同步粗略分為左下角的這幾個步驟。左上角我們列出了元數據同步的參與者。包括了RPC線程,就是Master端,來自于RPC的線程池。第2個參與者稱作同步線程池(sync thread pool)。第3個參與者稱作預取線程池(prefetch thread pool)。這裡有一個InodeTree,就是Alluxio裡面維護的所有文件的元數據,形成了一個樹狀的結構。圖中的UFS代表着實際的底層存儲。所有對UFS的連線都是一個對外部系統的RPC,是比較昂貴的操作。

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)22

圖22 元數據同步原理

同步步驟分三步:

① RPC線程向UFS讀取文件的元信息。在處理請求ls -R 時,對根節點全量的文件樹進行一次ls操作。此時基于時間戳,需要觸發元數據同步, RPC線程就會讀取文件根節點的信息,檢查挂載HDFS://alluxio根節點的信息。如果發現信息有更新,就去InodeTree裡面找根節點,則RPC線程對應地更新/創建/删除Alluxio的Inode元信息,并且這個節點進行更新。

② 如果在處理遞歸的時候,發現下面還有其他目錄,整棵樹都需要進行一次搜索,此時把遞歸文件/文件夾提交到同步線程池(sync thread pool)。用廣度優先搜索的方式進行遍曆,也就是常說的BFS。當提交這個任務後。會去同步線程池,在BFS的過程中,按照一定的順序遍曆這棵樹,data -> user -> others -> report …

在這個過程中,主要是做兩件事情:

  • 如果發現走到某個節點,需要對進行一次請求,它不會自己做這個請求,而是把這個請求交給預取線程池(prefetch thread pool)。
  • 如果發現下一步要去遍曆User -> others -> report …

就把任務提前交給預取線程池,告訴它去讀HDFS裡面相關的這些路徑,這也就是稱為預取的原因。在真正處理這個路徑之前,就提前告訴它,因為操作會需要很長的時間,保證性能最好的方式就是提前做這個事情;等任務處理到的時候,已經準備好了。這樣最高地利用了多線程的并發。

在處理每個節點的時候,确認預取線程池準備好的結果;如果有更新,就更新自己的InodeTree。

③ 預取線程池負責從讀取文件或者文件夾信息,把結果交給這個同步線程池,來加速這個具體的同步過程。

2. 性能優化-緩存

在這個時間原理的基礎上,進行了一系列的優化。

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)23

圖23 性能優化-緩存

首先就是做了緩存的優化。主要的設計理念就是因為UFS操作非常貴、非常慢,希望盡可能多的地緩存結果,節省的操作。

緩存優化涉及下面這幾種緩存:

  • 緩存了哪些路徑不存在,因為确定這個緩存不存在,需要去讀取UFS,又需要有一個外部的RPC;
  • 緩存哪些UFS文件最近被讀取過,和時間戳相互配合。知道上一次讀取的時間戳,就可以根據時間戳确定是否再次讀取;
  • 緩存UFS文件的具體信息,預取線程和同步線程用來交換信息的數據結構。在預取完之後把結果放到緩存裡,由這個同步線程将結果更新進Alluxio InodeTree。

3. 算法優化-鎖優化

在緩存優化之外,基于Alluxio的版本叠代,也做了各種各樣的元數據同步優化,其中比較大的就是算法的優化。

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)24

圖24 算法優化-鎖優化

在Alluxio2.3版本之前,所有的RPC線程是自己進行元數據的同步。如果遞歸基于DFS自己遍曆這棵樹,從頭到尾都持有路徑的寫鎖。如果是遞歸,實際上是寫鎖鎖住了整個子樹。在鎖住子樹的過程中,其他線程就無法讀取子樹裡的内容,并發度低,由于是單線程,做了非常多需要Block時間長的操作。

在Alluxio2.3裡面非常大的優化,就是把它改成了多線程并發同步的算法,更多利用線程池操作,DFS改成了BFS。根據需要,讀鎖升級,而非從頭至尾持有寫鎖。讀寫鎖的好處就是讓不同的線程之間有了更高的并發度。這樣在同步某一棵子樹的過程中,其他線程還有機會可以讀到這裡面的内容,所以整體的并發會更高。

4. 性能優化-調整并行度

第三個優化來自于用戶對線程池的配置。

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)25

圖25 性能優化-并行度

在Alluxio 2.3裡面加入了線程池之後,可以通過配置參數調整元數據同步的并行度。之前單線程沒有配置可言。調整并行度一般是通過這三個參數。

  • 第一個參數控制了單個RPC請求裡面的這個元數據同步,它的BFS并行度調的越高,并行度越高,更快的機會也就越大,同時對這個系統的占用也會越多;
  • 第二個是同步線程池大小;
  • 第三個是預取線程池大小。

兩個線城池的大小,建議配置成CPU數的倍數,具體比例以及系統應該配多大,取決于這兩個線程所做工作的時間,以及中間的配合方式。所以沒有給出統一建議,建議根據具體程序運行的時候,CPU比如可以做一些火焰圖、分析延遲以及inodetree更新的延遲,做一個更加合理的配比。默認的配比都是CPU的倍數,如果沒有在無數據同步看到非常明顯的瓶頸,不需要進行特别細粒度的調節。

--

06

對不同場景的推薦配置

最後針對不同的場景具體分析問題,推薦比較好的配置。

1. 場景1

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)26

圖26 場景一配置

最簡單的場景就是:所有的寫和讀全都經過了Alluxio。無疑Alluxio所有的元數據都是最新,此時無需做元數據同步。可以關閉元數據同步,提升性能。

2. 場景2

第二個場景稍微複雜一些。大部分的操作經過Alluxio,但是不排除還有一些場景,會繞過Alluxio直接改動原來裡面的文件。

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)27

圖27 場景二配置

在這種場景下,為了保證Alluxio和UFS元數據和數據的一緻,還是要保留一部分元數據同步的操作。在這裡分HDFS和非HDFS進行考慮,主要是因為這些HDFS比别人多一個選項Active Sync。

HDFS的情況下,需要考慮這幾個點:如果HDFS更新非常頻繁,就是繞過Alluxio的更新非常頻繁,或者HDFS的namenode的壓力比較大,不建議使用Active Sync,而是使用基于時間的被動同步。使用被動同步的原因是Active Sync是基于Alluxio心跳,去namenode拉取具體有哪些文件發生了改動,每一次拉取都是一次RPC,給namenode施加的壓力。同時如果文件發生了改動,Alluxio就又會向namenode發起RPC去同步這些文件。因此希望盡量減少這些操作來降低namenode的壓力。

如果基于時間的被動同步,能給予減少元數據同步操作的機會,則使用基于時間的被動同步;反之要使用Active Sync,因為更加主動,時效性更高。如果不會帶來性能負擔,完全可以去嘗試一下。

如果不是HDFS,隻能用基于時間的被動同步。

建議盡量節約元數據同步的操作,具體做法考慮每個數據、每個路徑更新的頻率大概是如何。基于這樣的考量,盡量給sync interval設一個比較大的值,盡量減少元數據的觸發。

3. 場景3

第三個場景稍微有些不同。大部分或全部更新都不經過Alluxio,而更新又非常頻繁。

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)28

圖28 場景三配置

在這種情況下,使用HDFS而且時效性又非常重要,使用Active Sync是唯一方案。因為如果把sync interval調到一個特别低的值,甚至可能觸發比Active Sync更多的同步。如果把它設成零之後,每一次都不會觸發同步,會進一步加大同步的操作開銷。

如果時效性并不十分重要,建議使用這個基于時間的被動同步。通過節省開銷,減少元數據同步的操作,就能提升系統的性能。同樣如果不是HDFS,則使用基于時間的被動同步。

以上是三個場景的分析,也是今天分享的全部内容。

--

07

答疑

Q:在ASYNC_THROUGH mode當中,因UFS原因導緻ASYNC上傳始終失敗,這種情況怎麼優雅地處理,以避免不一緻?

A:這個問題非常好,問到了痛點。目前沒有一個特别優雅的解決方案。

在異步方式下沒有call back,或者hook的自動介入,隻能人為介入。Alluxio2.4商業版中加入了一個job service dashboard查看異步任務的狀态。如果異步持久化失敗了,這個地方可以看到所有失敗的異步任務。目前隻能通過這個方式觀察究竟有哪些東西失敗了,然後再人為進行幹預。

我們已經注意到job service的問題,打算重新設計整個job service,從幾個方向,可擴展Scalability, Fault-tolerance,包括monitoring, failure mode, 恢複等。未來版本裡面會做出更好的設計,有很多場景,并加入人工幹預模式。通過開放一些接口,可以自動化地讀到這些東西,或是可能會增加界面,讓用戶定義一些方式。

Alluxio到了一個新的階段,要好好思考,用更加scalable的方案去解決這些問題。這些異步的操作已經提上了議事日程。

Q:和HDFS可以不同路徑設置不同的同步時間嗎?

A:可以用配置參數的方法去實現。

今天的分享就到這裡,謝謝大家。

閱讀更多技術幹貨文章、下載講師PPT,請關注微信公衆号“DataFunTalk”。


分享嘉賓:劉嘉承 Alluxio 核心組研發工程師

編輯整理:曾新宇 對外經貿大學

出品平台:DataFunTalk


分享嘉賓:

如何實現數據庫調優(劉嘉承從設計實現和優化角度淺談Alluxio元數據同步)29


關于我們:

DataFun:專注于大數據、人工智能技術應用的分享與交流。發起于2017年,在北京、上海、深圳、杭州等城市舉辦超過100 線下和100 線上沙龍、論壇及峰會,已邀請超過2000位專家和學者參與分享。其公衆号 DataFunTalk 累計生産原創文章700 ,百萬 閱讀,14萬 精準粉絲。


歡迎轉載分享評論,轉載請私信。

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关科技资讯推荐

热门科技资讯推荐

网友关注

Copyright 2023-2025 - www.tftnews.com All Rights Reserved