我們對 facebook 版本的 hadoop raid 分析發現,還有很多細節需要優化改進,本文就 hadoop raid 存在的問題進行**,並對一些可以改進的地方給出思路。
首先介紹一下 hadoop raid 的原理和架構:
原理分析
hdfs raid 以檔案為單位計算校驗,並將計算出來的校驗 block 儲存為乙個 hdfs檔案。 hdfs raid 支援 xor 和 rs 兩種編碼方式,其中 xor 以位異或生成校驗資訊;而 rs 又稱裡所碼,即 reed-solomon codes ,是一種糾錯能力很強的通道編碼,被廣泛應用在 cd 、 *** 和藍光光碟的資料糾錯當中。
hdfs 為每個 block 建立 3 個副本,可以容忍 2 個 block 丟失,因此儲存空間為資料量的 3 倍。而採用 rs 編碼,如按條帶( stripe length )和校驗塊( parity block )個數比例為 10,4 計算,則只需要 1.4 倍的儲存開銷,就可以容忍同一條帶內任意 4 個block 丟失,即儲存量可以節省 16/30 。
hadoop raid 架構
drfs
l drfs :應用 raid 方案後的 hdfs
l raidnode :根據配置路徑,對需要 raid 的檔案( source file ),從 hdfs datanode 中讀取對應的資料塊,計算出校驗塊檔案( parity file ,所有校驗塊組成乙個 hdfs 檔案),並將 parity file 儲存在 hdfs 中; raidnode 週期性的檢查原始檔及校驗塊檔案對應的 block 資料是否丟失,如有丟失,則重新計算以恢復丟失的 block
l raid file system :提供訪問 drfs 的 hdfs 客戶端,其在 hdfs client 介面上進行封裝,當讀取已丟失或損壞的 block 時,通過對應的校驗塊計算恢復的 block 資料返回給應用,恢復過程對應用是透明的
l raidshell : drfs 管理工具,可手工觸發生成 parity file 、恢復丟失 block 等
問題與優化
l 問題 1 集群壓力增加
集群壓力增加表現為 namenode 元資料增多、訪問量增加、 raid 和資料恢復時集群網路及 io 負載增加幾個方面,具體如下:
其一, raid 過程中會生成校驗檔案以及目錄結構,導致元資料增加。如下圖所示,對於每乙個原始檔案,都會在目標目錄生成乙個對應的檢驗檔案,造成元資料量double 。由於校驗檔案讀操作遠大於刪除等更新操作,解決方案為對校驗檔案做 har打包,將目錄打包成乙個 har 檔案,以節省元資料量。
其二, raidnode 週期性的訪問 namenode ,查詢哪些檔案需要做 raid 、是否存在廢棄的 parity file (原始檔被刪除,則對應的 parity file 已經無效了,需要清理掉)、是否存在 missing block 等,這些操作都對 namenode 產生一定壓力。解決方案為調整raidnode 訪問 namenode 的頻率,控制在可接受的範圍。
其三,做 raid 生成校驗檔案及恢復丟失的 block 時,需要讀取相同 stripe 的多個block 資料,導致集群內網路及 io 負載增加。解決方案為選擇空閒時段進行操作,減少對現網生產環境的影響。
其四, raid 完成後,原始檔 block 副本數減少, job 本地化概率減小,同時增加了網路流量和 job 的執行時間。為減少影響,只對訪問頻率較低的冷資料做 raid ,而冷資料的判定,則需要從資料生成時間、訪問時間、訪問次數綜合考慮。
l 問題 2 集群效能下降
效能下降則包括塊刪除速度變慢、讀取頻繁移動的塊速度變慢,具體如下:
其一, namenode 應用 raid 塊放置策略,刪除 block 需要考慮相同 stripe 的其他block 的位置情況,以保證同一 datanode 上不會儲存該 stripe 的多個 block ,避免由於該 datanode 故障缺失過多的塊,造成資料無法恢復的風險。另外,在集群啟動時, namenode 要重建元資料資訊,同時對比 block 的實際副本數和配置值,用以刪除和增加 block ;由於 raid 塊放置策略的引入,每個 block 的增加和刪除都需要考慮相同 stripe 的其他 block 位置資訊,這一過程非常耗時,導致 namenode 啟動變慢很多。
解決方案是,在啟動時使用預設的塊放置策略,保持啟動過程同原有流程相同,待啟動完成,再修改為 raid 塊放置策略,動態重新整理到 namenode 生效。
其二, raidnode 週期性的掃瞄原始檔案和檢驗檔案,如發現同一 datanode 上儲存該 stripe 內的過多 block ,則將超出來的 block 遷移到其他 datanode 上。raidnode 的檢查週期預設值為 10 分鐘,然而塊移動過程 namenode 並不會及時清掉 block 同移出 datanode 的對映關係,而要等到下次 datanode 塊上報,塊上報的週期比較長,一般 2 個小時。這樣在下次塊上報之前, namenode 中 block 對映的datanode 會不斷累積,直至遍布整個集群。客戶端讀取這個 block 資料就會因很多datanode 上並不存在塊檔案而重試,導致效能下降。解決方案為調整 raidnode 掃瞄週期,要大於 datanode 的塊上報週期,期間 namenode 來修正 block 和 datanode的對映關係。
l 問題 3 資料安全性問題
表現在 rebalance 不理解 raid 概念:
rebalance 不理解 raid 的條帶的概念,將 block 在集群中重新移動後,可能會導致相同 stripe 的多個 block 儲存在相同的 datanode 上,存在丟塊的風險。解決方案為namenode 增加 rpc 介面,查詢 block 所屬檔案,進而結合 raid 塊放置策略,將stripe 的多個 block 分散得更散。
l 問題 4 raid 過程 job 資料傾斜
raidnode 提交 job 對多個原始檔做 raid ,理想效果如圖 (a) ,多個檔案平均分配到每個 map 中 raid 操作,但執行過程中發現大部分 map 迅速完成,統計讀取記錄為 0,而另外少部分 map 執行時間較長。
分析流程發現, raidnode 採用同 distcp 相同的方式,先將需要 raid 的檔案列表,以 sequencefile 格式寫入 hdfs ,且每 10 個檔案寫入一次 sync 標識,分片時再將每個檔案構造成 filesplit 作為分片單元; map 讀取輸入使用sequencefilerecordreader ,以 sync 標識為起止位置。以 (b) 圖為例, map1 的起止位置跨越了 sync1 ,因讀取的資料為 sync1 和 sync2 之間的 10 個檔案列表,而其它 map 的起止位置在同一 sync 區間內,則讀取資料為 0 ,這就是 job 傾斜的原因。
解決方案為每個檔案後面都寫入一次 sync 標識,多個檔案就會平均分配到 map 中執行。而 sync 標識占用 20 個位元組,且只在 job 執行結束 sequencefile 就會清理掉,儲存代價微乎其微。
MongoDB實戰經驗分享
nosql並不是no sql,而是指not only sql。nosql的出現是為了彌補sql資料庫因為事務等機制帶來的對海量資料 高併發請求的處理的效能上的欠缺。nosql不是為了替代sql而出現的,它是一種替補方案,而不是解決方案的首選。絕大多數的nosql產品都是基於大記憶體和高效能隨機讀寫的...
Spark專案實戰經驗
auto.offset.reset 啟動時讀取的偏移量。如果是需要歷史資料那麼設定成earliest 如果不需要消費歷史資料那麼設定成latest 1 如果自動提交偏移量 spark streaming消費到資料之後立馬提交,那麼就會有乙個問題 提交偏移量成功 處理失敗了,那麼spark strea...
雜湊表實戰經驗
雜湊表的作用 簡單來說就是將乙個龐大的值域 複雜的資料結構 對映到乙個較小的空間 例如0 n,n 為1e5或1e6等比較小的數 通常寫雜湊函式最簡單方法就是 例如 h x x mod 10 5,將很大的x對映到10 5內。但是往往會面臨衝突,因為值域太大,經過雜湊函式的計算對映的值相同。那麼如何處理...