1. 程式人生 > >HDFS中的集中化快取管理

HDFS中的集中化快取管理

 

2016年04月19日 21:30:07 Free World 閱讀數:783

概述


 

HDFS中的集中化快取管理是一個明確的快取機制,它允許使用者指定要快取的HDFS路徑。NameNode會和儲存著所需快資料的所有DataNode通訊,並指導他們把塊資料快取在off-heap快取中。

HDFS集中化快取管理具有許多重大優勢:

1.明確的鎖定可以阻止頻繁使用的資料被從記憶體中清除。當工作集的大小超過了主記憶體大小(這種情況對於許多HDFS負載都是司空見慣的)時,這一點尤為重要。

2.由於DataNode快取是由NameNode管理的,所以,在確定任務放置位置時,應用程式可以查詢一組快取塊位置。把任務和快取塊副本放在一個位置上可以提高讀操作的效能。

3.當塊已經被DataNode快取時,客戶端就可以使用一個新的更高效的零拷貝讀操作API。因為快取資料的checksum校驗只需由DataNode執行一次,所以,使用這種新API時,客戶端基本上不會有開銷。

4.集中快取可以提高整個叢集的記憶體使用率。當依賴於每個DataNode上作業系統的buffer快取時,重複讀取一個塊資料會導致該塊的N個副本全部被送入buffer快取。使用集中化快取管理,使用者就能明確地只鎖定這N個副本中的M個了,從而節省了N-M的記憶體量。

 

使用場景


 

集中化快取管理對於重複訪問的檔案很有用。例如,Hive中的一個較小的fact表(常常用於joins操作)就是一個很好的快取物件。另一方面,對於一個全年報表查詢的輸入資料做快取很可能就沒有多大作用了,因為,歷史資料只會讀取一次。

集中化快取管理對於帶有效能SLA的混合負載也很有用。快取正在使用的高優先順序負載可以保證它不會和低優先順序負載競爭磁碟I/O。

 

架構


 

Caching Architecture

 

在這個架構中,NameNode負責協調叢集中所有DataNode的off-heap快取。NameNode週期性地接收來自每個DataNode的快取報告(其中描述快取在給定DN中的所有塊)。NameNode通過藉助DataNode心跳上的快取和非快取命令來管理DataNode快取。

NameNode查詢自身的快取指令集來確定應該快取那個路徑。快取指令永遠儲存在fsimage和edit日誌中,而且可以通過Java和命令列API被新增、移除或修改。NameNode還儲存了一組快取池,它們是用於把資源管理類和強制許可權類的快取指令進行分組的管理實體。

NameNode週期性地重複掃描名稱空間和活躍的快取指定以確定需要快取或不快取哪個塊,並向DataNode分配快取任務。重複掃描也可以又使用者動作來觸發,比如,新增或刪除一條快取指令,或者刪除一個快取池。

當前,我們不快取construction、corrupt下的塊資料,或者別的不完整的塊。如果一條快取指令包含一個符號連結,那麼該符號連結目標不會被快取。

當前,我們只實現了檔案或目錄級的快取。塊和子塊快取是未來的目標。

 

概念


 

快取指令

一條快取指令定義了一個要被快取的路徑(path)。這些路徑(path)可以是資料夾或檔案。資料夾是以非迭代方式快取的,只有在資料夾頂層列出的檔案才有意義。

資料夾也可以指定額外的引數,比如快取副本因子,有效期等。副本因子指定了要快取的塊副本數。如果多個快取指令指向同一個檔案,那麼就用最大快取副本因子。

有效期是在命令列指定的,就像TTL一樣,相對有效期會在未來版本引入。快取指令過期之後,在決定快取時,它就不再被NameNode考慮了。

 

快取池

快取池是一個管理實體,用於管理快取指令組。快取池擁有類UNIX的許可權,可以限制哪個使用者和組可以訪問該快取池。寫許可權允許使用者向快取池新增或從中刪除快取指令 。讀許可權允許使用者列出快取池內的快取指令,還有其他元資料。執行許可權不能使用。

快取池也可以用於資源管理。它可以強加一個最大限制值,可以限制通過快取池中的指令快取入的位元組數。通常,快取池限制值之和約等於為HDFS在叢集中做快取而保留的總記憶體量。快取池也可以追蹤許多統計資訊以便於叢集使用者決定應該快取什麼。

快取池也可以強加一個TTL最大值。該值限制了被新增到快取池的指令的最大有效期。

 

快取管理命令介面


 

在命令列上,管理員和使用者可以使用過hdfs cacheadmin子命令藉助快取池來互動。

快取指令由一個唯一的無重複的64位整數ID來標識。即使快取指令後來被刪除了,ID也不會重複使用。

快取池由一個唯一的字串名稱來標識。

 

快取管理命令

addDirective

用法: hdfs cacheadmin -addDirective -path <path> -pool <pool-name> [-force] [-replication <replication>] [-ttl <time-to-live>]

<path> 要快取的路徑。該路徑可以是資料夾或檔案。
<pool-name> 要加入快取指令的快取池。你必須對改快取池有寫許可權以便新增新的快取指令。
-force 不檢查快取池的資源限制
<replication> 要使用的快取副本因子,預設為1
<time-to-live>  快取指令可以保持有效多長時間。可以按照分鐘,小時,天來指定,如30m,4h,2d。有效單位為[smhd]。“never”表示永不過期的指令。如果未指定該值,那麼,快取指令就不會過期。

 

removeDirective

用法: hdfs cacheadmin -removeDirective <id>

<id>  要刪除的快取指令的ID。你必須對該指令的快取池擁有寫許可權,以便刪除它。要檢視詳細的快取指令列表,可以使用-listDirectives命令。

 

removeDirectives

用法: hdfs cacheadmin -removeDirectives <path>

<path>  要刪除的快取指令的路徑。你必須對該指令的快取池擁有寫許可權,以便刪除它。要檢視詳細的快取指令列表,可以使用-listDirectives命令。

 

listDirectives

用法:hdfs cacheadmin -listDirectives [-stats] [-path <path>] [-pool <pool>]

<path>  只列出帶有該路徑的快取指令。注意,如果路徑path在快取池中有一條我們沒有讀許可權的快取指令,那麼它就不會被列出來。
<pool>  只列出該快取池內的快取指令。
-stats  列出基於path的快取指令統計資訊。

 

 

快取池命令

 

addPool

用法:hdfs cacheadmin -addPool <name> [-owner <owner>] [-group <group>] [-mode <mode>] [-limit <limit>] [-maxTtl <maxTtl>

<name>  新快取池的名稱。
<owner>  該快取池所有者的名稱。預設為當前使用者。
<group>  快取池所屬的組。預設為當前使用者的主要組名。
<mode>  以UNIX風格表示的該快取池的許可權。許可權以八進位制數表示,如0755.預設值為0755.
<limit>  在該快取池內由指令總計快取的最大位元組數。預設不設限制。
<maxTtl>  新增到該快取池的指令的最大生存時間。該值以秒,分,時,天的格式來表示,如120s,30m,4h,2d。有效單位為[smhd]。預設不設最大值。“never”表示沒有限制。

 

 

modifyPool

用法:hdfs cacheadmin -modifyPool <name> [-owner <owner>] [-group <group>] [-mode <mode>] [-limit <limit>] [-maxTtl <maxTtl>]

<name>  要修改的快取池的名稱。
<owner>  該快取池所有者的名稱。
<group>  快取池所屬的組。
<mode>  以UNIX風格表示的該快取池的許可權。八進位制數形式。
<limit>  在該快取池內要快取的最大位元組數。
<maxTtl>  新增到該快取池的指令的最大生存時間。

 

 

removePool

用法:hdfs cacheadmin -removePool <name>

<name> 要刪除的快取池的名稱

 

 

listPools

用法:hdfs cacheadmin -listPools [-stats] [<name>]

-stats 顯示額外的快取池統計資訊
<name> 若指定,則僅列出該快取池的資訊

 

 

help

用法:hdfs cacheadmin -help <command-name>

<command name> 要獲得詳細幫助資訊的命令。如果沒有指定命令,則列印所有命令的幫助資訊。

配置


 

本地庫

為了把塊檔案鎖定在記憶體,DataNode需要依賴本地JNI程式碼(Linux系統為libhadoop.so,Windows系統為hadoop.dll)。如果你正在使用HDFS集中化快取管理,請確保使能JNI

 

配置屬性

屬性名稱 預設值 描述
dfs.datanode.max.locked.memory 0 DataNode的記憶體中快取塊副本要用的記憶體量(以位元組表示)。DataNode的最大鎖定記憶體軟限制ulimit(RLIMIT_MEMLOCK)必須至少設為該值。 否則,DataNode在啟動時會終止。預設值為0,表示禁止記憶體快取。如果本地庫對於該DataNode不可用,那麼,該配置就無效。 
dfs.namenode.list.cache.directives.num.responses 100 該引數控制NameNode在響應listDirectives RPC命令時通過wire傳送的快取指令數。
dfs.namenode.list.cache.pools.num.responses 100 該引數控制NameNode在響應listDirectives RPC命令時通過wire傳送的快取池數。
dfs.namenode.path.based.cache.refresh.interval.ms 30000 兩次子路徑快取重複掃描的時間間隔,單位毫秒。路徑快取重複掃描發生在計算快取哪個塊,以及在哪個DataNode上快取時。預設為30秒。 
dfs.namenode.path.based.cache.retry.interval.ms 30000 當NameNode不需要快取某些資料,或者快取那些沒有快取的資料時,它必須通過在DataNode心跳響應中傳送DNA_CACHE或者DNA_UNCACHE命令,以便指導DataNode這麼去做。該引數控制NameNode重複傳送這些命令的頻率。(即多長時間重發一次)
dfs.datanode.fsdatasetcache.max.threads.per.volume 4 DataNode上快取新資料時每個卷要用的最大執行緒數。 這些執行緒要消耗I/O和CPU。該引數影響普通DataNode操作。
dfs.cachereport.intervalMsec 10000 決定兩次快取上報動作的時間間隔,單位毫秒。超過這個時間後,DataNode會向NameNode傳送其快取狀態的完整報告。 NameNode使用快取報告來更新快取塊與DataNode位置之間的對映關係。如果記憶體快取被禁用了(設定屬性dfs.datanode.max.locked.memory為0,這是預設值),那麼該引數就無效了。如果本地庫對於該DataNode不可用,那麼,該配置就無效。
dfs.datanode.cache.revocation.timeout.ms 900000 當DFSClient從DataNode正在快取的塊檔案中讀取資料時,DFSClient可以不做checksums校驗。DataNode一直將塊檔案儲存在快取中直到客戶端完成。然而,如果客戶端一改往常般運行了很長時間,那麼,DataNode可能需要從快取中清除這個塊檔案。該引數控制DataNode等待一個正在執行無校驗讀操作的客戶端傳送一個副本要花多少時間。
dfs.datanode.cache.revocation.polling.ms 500 DataNode需要多長時間輪詢一次客戶端是否停止使用DataNode不想快取的副本。

 

必選屬性

屬性名稱 預設值 描述
dfs.datanode.max.locked.memory   該引數用於確定DataNode給快取使用的最大記憶體量。DataNode使用者的“locked-in-memory size”ulimit(ulimit -l)也需要增加以匹配該引數(詳見下文OS限制)。當設定了該值時,請記住你還需要一些記憶體空間用於做其他事情,比如,DataNode和應用程式JVM堆記憶體、以及作業系統的頁快取。

 

可選屬性

以下屬性不是必選的,但可能用於調優:

屬性名稱 預設值 描述
dfs.namenode.path.based.cache.refresh.interval.ms 300000 NameNode使用該引數作為兩次子路徑快取重複掃描的動作之間的時間間隔,單位為毫秒。該引數計算要快取的塊和每個DataNode包含一個該塊應當快取的副本。
dfs.datanode.fsdatasetcache.max.threads.per.volume 4 DataNode使用該引數作為快取新資料時每個卷要用的最大執行緒數。
dfs.cachereport.intervalMsec 10000 DataNode使用該引數作為兩次傳送快取狀態報告給NameNode的動作之間的時間間隔。單位為毫秒。
dfs.namenode.path.based.cache.block.map.allocation.percent 0.25 分配給已快取塊對映的Java堆記憶體的百分比。它是hash map,使用鏈式hash。如果快取塊的數目很大,那麼map越小,訪問速度越慢;map越大,消耗的記憶體越多。

 

 

OS限制

如果你遇到錯誤“Cannot start datanode because the configured max locked memory size... is more than the datanode's available RLIMIT_MEMLOCK ulimit,”,就意味著作業系統對使用者可以鎖定的記憶體使用量強加了一個限制,該限制值比使用者設定的值更低一些。要修復這個問題,必須使用“ulimit -l”命令來調整DataNode執行需要鎖定的記憶體值。通常,該值是在/etc/security/limits.conf檔案中配置的。然而,它也會因使用者所用的操心繫統和分發版的不同而變化。

當你從shell中執行“ulimit -l”並得到一個比你用屬性dfs.datanode.max.locked.memory設定的值更高的值,或者字串“ulimited”(表示沒有限制)時,你就會明白你已經正確配置了該值。值得注意的是,ulimit -l命令通常以KB為單位輸出記憶體鎖定限制值,但是dfs.datanode.max.locked.memory的值必須以位元組為單位。

這些資訊不適用於Windows環境部署。Windows沒有和“ulimit -l”相對應的命令。

 

 

本文系從官方文件翻譯而來,轉載請尊重譯者的工作,註明以下連結:

http://www.cnblogs.com/zhangningbo/p/4146398.html