概覽
HDFS上的中心化緩存是一個(gè)顯式的緩存機(jī)制, 使得用戶可以指定哪個(gè)路徑被緩存. Namenode和擁有指定文件塊的DataNode們通訊, 并命令他們將文件塊緩存到堆外緩存中.
HDFS的中心化緩存管理有如下的明顯優(yōu)勢:
明確的固定(pinning)可以防止被頻繁使用的數(shù)據(jù)被從內(nèi)存中移除. 這對那些數(shù)據(jù)尺寸超過主存的情況很重要, 而這類情況在HDFS上是非常常見.
因?yàn)镈ataNode的緩存是由NameNode管理的, 應(yīng)用方可以查詢被緩存的文件塊的位置, 并決定任務(wù)的位置. 將任務(wù)和緩存的文件塊副本放在一起改善了讀的性能.
當(dāng)文件塊被DataNode緩存后, 客戶端可以使用更新, 更高效, 和零拷貝的讀API. 因?yàn)榫彺嫖募K的校驗(yàn)和驗(yàn)證由DataNode執(zhí)行了一次, 客戶端就能以0開銷地使用新API(問: 什么新API?).
中心化緩存可以改善整個(gè)集群的內(nèi)存使用情況. 當(dāng)只能依靠各個(gè)DataNode的操作系統(tǒng)高速緩存時(shí), 重復(fù)地讀取一塊文件塊會導(dǎo)致該塊的n個(gè)拷貝被讀入高速緩存. 使用中心化緩存管理后, 一個(gè)用戶可以顯示指定只有n個(gè)副本中的m個(gè)可以被固定在緩存中, 并節(jié)省n-m的內(nèi)存.
使用場景
中心化緩存對于被常重復(fù)訪問的文件非常有用. 例如, Hive里一個(gè)較小的事實(shí)表, 經(jīng)常要和其他表在查詢中連接, 這就是需要被緩存的一個(gè)好候選.
反之, 緩存一個(gè)某年的查詢報(bào)告就沒那么必要, 因?yàn)闅v史數(shù)據(jù)一般就被讀一次.
中心化緩存管理對那種有服務(wù)等級協(xié)議(SLA)有多樣差異化的運(yùn)行負(fù)載也非常有用. 緩存那些優(yōu)先級高的的工作集數(shù)據(jù), 可以保證它不用和低優(yōu)先級的工作集數(shù)據(jù)競爭磁盤IO. (就像機(jī)場的VIP候機(jī)廳)
架構(gòu)

在這個(gè)架構(gòu)中, NameNode負(fù)責(zé)協(xié)調(diào)集群中所有DataNode的堆外緩存. NameNode定期地接收各個(gè)DataNode發(fā)送過來的緩存報(bào)告, 報(bào)告描述了任意DataNode上被緩存的所有文件塊. NameNode通過在心跳響應(yīng)中發(fā)送的緩存和踢出緩存命令來管理DataNode上的緩存.
NameNode查詢自身的緩存指令(directives?)來決定哪些路徑應(yīng)該被緩存. 緩存指令被永久存儲在文件系統(tǒng)映像(fsimage)和操作日志(edit log)中, 并且可以把java和命令行的api進(jìn)行添加,刪除和修改. NameNode也存儲了一些緩存池, 這些管理實(shí)體被用來將緩存指令分組, 進(jìn)行資源管理和權(quán)限控制.
NameNode定期地掃描命名空間和緩存指令來決定,哪些文件塊要被緩存,哪些要踢出緩存, 并將緩存動作指派到DataNode上. 掃描亦可由用戶動作發(fā)起, 例如添加或者刪除緩存指令, 或刪除一個(gè)緩存池.
我們當(dāng)前不會緩存那些, 構(gòu)建中, 損壞或者不完整的文件塊. 如果一個(gè)緩存指令涉及到文件鏈接, 這個(gè)鏈接的目標(biāo)文件不會被緩存.
當(dāng)前可以緩存文件或者目錄. 文件塊或更低級別的緩存將在未來實(shí)現(xiàn).
概念
緩存指令
一個(gè)緩存指令定義了要緩存的一個(gè)路徑. 路徑可以是目錄或者文件. 目錄是不會被遞歸式緩存的, 只有當(dāng)前目錄這一級的文件會被緩存.
指令同時(shí)定義了額外參數(shù), 例如緩存復(fù)制因子和過期時(shí)間. 緩存復(fù)制因子指定緩存要復(fù)制多少次. 如果多個(gè)緩存指令要緩存某一個(gè)文件, 那么最大緩存復(fù)制因子就被應(yīng)用.
過期時(shí)間由命令行指定為存活時(shí)間(time-to-live, TTL), 一個(gè)在未來的相對時(shí)間. 當(dāng)一個(gè)緩存指令過期后, 就不會再被NameNode在做緩存決定時(shí)考慮到.
緩存池
緩存池作為一個(gè)管理實(shí)體, 管理著緩存指令的分組. 緩存池有一個(gè)UNIX那種權(quán)限, 限制哪些用戶和組可以訪問某個(gè)池. 寫權(quán)限允許用戶在某個(gè)池上添加和刪除緩存指令. 讀權(quán)限允許用戶列出一個(gè)池中的緩存指令, 讀額外的元數(shù)據(jù). 執(zhí)行權(quán)限目前沒用到.
緩存池也用以管理資源. 池可以指定當(dāng)前池中能緩存的數(shù)據(jù)尺寸的最大限制(byte). 通常, 所有池的緩存限制之和,等于HDFS集群中所有的保留內(nèi)存(哪里指定?)之和. 緩存池同時(shí)也跟蹤記錄了很多統(tǒng)計(jì)來提升用戶如何決定什么應(yīng)該被緩存.
池也可以強(qiáng)制定義一個(gè)最大存活時(shí)間TTL. 這個(gè)定義限制了緩存指令在這個(gè)池中的最大存活時(shí)間.
緩存管理 命令行接口
在命令行下, 管理員和用戶可以通過hdfs cacheadmin命令集, 來操作緩存池和緩存指令.
緩存指令通過一個(gè)唯一, 不重復(fù)的64位整數(shù)ID來識別. 即使這個(gè)緩存指令被刪掉后, ID也不會被重復(fù)使用.
緩存指令命令
addDirective
用法: hdfs cacheadmin -addDirective -path 路徑 -pool 緩存池名 [-force] [-replication 復(fù)制因子] [-ttl 存活時(shí)間]
添加一個(gè)新的緩存指令
| 參數(shù) | 說明 |
|---|---|
| 路徑 | 要緩存的路徑, 這個(gè)路徑可以是目錄或文件(通配符可以嗎?) |
| 緩存池名 | 要把這個(gè)緩存指令加到哪個(gè)緩存池中. 你必須要有這個(gè)緩存池的寫權(quán)限才能加緩存指令 |
| -forece | 不檢查這個(gè)緩存池的最大尺寸限制 |
| 緩存復(fù)制因子 | 緩存復(fù)制多少份,默認(rèn)是1 |
| 存活時(shí)間 | 這個(gè)緩存指令的有效期, 可以指定為分鐘, 小時(shí), 天. 例如 30m, 4h, 2d. 有效單位是smhd. 用"never"來指定一個(gè)緩存永遠(yuǎn)存活, 如果不指定, 這個(gè)緩存指令就永不過期 |
removeDirective
用法: hdfs cacheadmin -removeDirective <Id>
刪除一個(gè)緩存指令
| 參數(shù) | 說明 |
|---|---|
| id | 要?jiǎng)h除的緩存指令的id, 你必須有這個(gè)緩存指令的緩存池的寫權(quán)限才能刪除它. 要列出緩存指令的id, 請用-listDirectives命令 |
removeDirectives
用法: hdfs cacheadmin -removeDirectives 路徑
刪除指定路徑相關(guān)所有的緩存指令
| 參數(shù) | 說明 |
|---|---|
| 路徑 | 要?jiǎng)h除的緩存指令的路徑, 你必須有這個(gè)緩存指令的緩存池的寫權(quán)限才能刪除它. 要列出緩存指令的id, 請用-listDirectives命令 |
listDirectives
用法: hdfs cacheadmin -listDirectives [-stats] [ -path 路徑 ] [ -pool 池]
列出緩存指令
| 參數(shù) | 說明 |
|---|---|
| 路徑 | 只列出這個(gè)路徑相關(guān)的緩存指令. 注意, 如果對應(yīng)這個(gè)路徑的某個(gè)緩存指令所在的緩存池你沒有讀權(quán)限, 那這個(gè)緩存指令就不會列出. |
| 緩存池 | 只列出這個(gè)緩存池中的緩存指令 |
| -stats | 列出基于路徑的緩存指令統(tǒng)計(jì)匯總 |
緩存池命令
addPool
用法: hdfs cacheadmin -addPool 緩存池名 [-owner 所有者用戶名] [-group 用戶組] [-mode 模式] [-limit 尺寸限制] [-maxTtl 最大存活時(shí)間]
| 參數(shù) | 說明 |
|---|---|
| 緩存池名 | 緩存池的名字(最大長度?特殊字符?) |
| 所有者 | 這個(gè)緩存池所有者的用戶名, 默認(rèn)是當(dāng)前用戶名 |
| 用戶組 | 這個(gè)池的用戶組. 默認(rèn)值是當(dāng)前用戶的主組的名字 |
| 模式 | 這個(gè)池的UNIX風(fēng)格的權(quán)限模式. 權(quán)限模式用8進(jìn)制表示. 例如. 0755. 默認(rèn)值是0755 |
| 尺寸限制 | 結(jié)合這個(gè)池上所有緩存指令, 這個(gè)池能緩存的最大字節(jié)數(shù). 默認(rèn)值是沒有限制 |
| 最大存活時(shí)間 | 對這個(gè)池,緩存指令能指定的最大存活時(shí)間. 可以指定為 秒, 分, 時(shí), 天. 例如 120s, 30m, 4h, 2d. 有效單位是[smhd]. 默認(rèn)是沒有最大值限制. 也可以用"never"來表示沒有限制 |
modifyPool
用法: hdfs cacheadmin -modifyPool 緩存池名 [-owner 所有者用戶名] [-group 用戶組] [-mode 模式] [-limit 尺寸限制] [-maxTtl 最大存活時(shí)間]
修改一個(gè)已經(jīng)存在的緩存池的元數(shù)據(jù)
| 參數(shù) | 說明 |
|---|---|
| 緩存池名 | 緩存池的名字 |
| 所有者 | 這個(gè)緩存池所有者的用戶名 |
| 用戶組 | 這個(gè)池的用戶組 |
| 模式 | 這個(gè)池的Unix風(fēng)格的8進(jìn)制權(quán)限 |
| 尺寸限制 | 這個(gè)池能緩存的最大byte數(shù) |
| 最大存活時(shí)間 | 這個(gè)池里緩存指令的最大存活時(shí)間 |
listPools
用法: hdfs cacheadmin -listPools [-stats] [名字]
列出一個(gè)或者多個(gè)緩存池的信息, 例如: 名字, 所有者, 權(quán)限, 等等
| 參數(shù) | 說明 |
|---|---|
| -stats | 顯示為額外緩存池的統(tǒng)計(jì)信息 |
| 名字 | 如果指定, 只列出命名為此的緩存池 |
help
用法: hdfs cacheadmin -help 命令名
顯示某個(gè)命令的詳細(xì)幫助信息
| 參數(shù) | 說明 |
|---|---|
| 命令名 | 要查看幫助的命令. 如果沒有指定,顯示所有命令的詳細(xì)幫助 |
配置
Native Libraries (原生庫)
為了將文件塊鎖定在內(nèi)存中, DataNode依賴于libhadoop.so或者h(yuǎn)adoop.dll(windows)中的JNI代碼. 要用HDFS中心緩存管理, 請確保啟動JNI.
配置屬性
必須項(xiàng)
確保以下配置:
- dfs.datanode.max.locked.memory
這個(gè)屬性決定一個(gè)DataNode可以用以緩存的最大內(nèi)存數(shù)量. 在Unix類系統(tǒng), "locked-in-memorysize" 在ulimit(ulimit -l)中, DataNode的用戶必須將其增加到和這個(gè)屬性配置對應(yīng)的值. (請參考OS限制). 配置這個(gè)值時(shí), 請留意其他需要內(nèi)存的程序, 例如DataNode和Jvm應(yīng)用堆內(nèi)存和操作系統(tǒng)緩存.
這個(gè)配置和延遲序列化寫特性共享. 數(shù)據(jù)節(jié)點(diǎn)會確保中心化緩存管理和延遲序列化寫特性所使用的內(nèi)存的總額不會超過dfs.datanode.max.locked.memory配置的值.
可選項(xiàng)
以下配置屬性不是必須的, 但可能用于調(diào)優(yōu):
dfs.namenode.path.based.cache.refresh.interval.ms
NameNode用這個(gè)配置的毫秒數(shù)為周期進(jìn)行路徑緩存掃描. 這個(gè)掃描計(jì)算要緩存的文件塊和要緩存文件塊副本的各個(gè)DataNode
默認(rèn)下, 這個(gè)參數(shù)的值是300000毫秒, 5分鐘.dfs.datanode.fsdatasetcache.max.threads.per.volume
DataNode用這個(gè)配置作為每個(gè)卷的最大線程數(shù), 來緩存新數(shù)據(jù).
默認(rèn)下, 這個(gè)參數(shù)是4dfs.cachereport.intervalMsec
DataNode以這個(gè)毫秒數(shù)為周期來向NameNode發(fā)送其緩存狀態(tài)的報(bào)告
默認(rèn)下, 這個(gè)參數(shù)是10000毫秒, 10秒鐘.dfs.namenode.path.based.cache.block.map.allocation.percent
這個(gè)參數(shù)決定我們要分配多少Java堆內(nèi)存給緩存文件塊map. 緩存文件塊map是一個(gè)用鏈?zhǔn)焦5囊粋€(gè)哈希map. 如果map比較小,而緩存的文件塊數(shù)量大, 那訪問map速度就慢. 比較大的map會消耗更多內(nèi)存. 默認(rèn)值是0.25%.
OS Limits 操作系統(tǒng)限制
如果你看到這個(gè)錯(cuò)誤:"Cannot start datanode because the configured max locked memory size… is more than the datanode’s available RLIMIT_MEMLOCK ulimit" (無法啟動DataNode, 因?yàn)榕渲玫膍ax locked memory大于DataNode可用的RLIMIT_MEMLOCK ulimit). 這個(gè)表示操作系統(tǒng)配置的內(nèi)存限制比你配置在HDFS里的要小. 要修復(fù), 你要調(diào)整DataNode運(yùn)行的ulimit -l值. 通常, 這個(gè)值是配置在 /etc/security/limits.conf 文件. 不過, 也取決于你使用的操作系統(tǒng)的版本.
當(dāng)你可以從shell里執(zhí)行"ulimit -l"并得到一個(gè)值大于你配置到dfs.datanode.max.locked.memory的值,或者"unlimited",意味著沒有限制,就說明你已經(jīng)正確地配置了系統(tǒng)的限制. 請注意, "ulimit -l"命令輸出的memory lock limit的單位是KB,但dfs.datanode.max.locked.memory的單位必須指定為byte.
這個(gè)提示并不能應(yīng)用到windows上的部署. 因?yàn)閣indows上沒有"ulimit -l"對應(yīng)的命令
引用:
https://blog.csdn.net/chenKFKevin/article/details/61196409