寫在前面的話
Hdfs採用分佈式架構,爲上層的應用和用戶提供可擴展、高吞吐、高可靠的數據存儲服務。在整個Hadoop生態系統中,hdfs處於最底層,也是最無可替代的一個基礎設施。從2008年hadoop-0.10.1版本開始到現在的hadoop-3.0.0-beta1,hdfs已經走過了近10個年頭,其架構和功能特性也發生了巨大的變化。特別是hdfs3.0.0系列,和hdfs2.x相比,增加了基於糾刪碼(erasure encoding)的容錯方式,與傳統的副本方式相比,在同等可用性的情況下, 能大幅節省一半以上的空間,這也是自hdfs誕生近這十年來,數據可靠性機制上的一個重大變化(之前一直都是副本容錯方式)。此外hdfs3.0.0還增加了其它的一些特性,例如在Namenode HA中支持3個Namenode,可以容忍2個Namenode失效,而hdfs2.x只能容忍1個Namenode失效。
本文以連載的方式,在“大數據學習網”上記錄自己使用hadoop-3.0.0-beta1的hdfs的點點滴滴,包括從零開始搭建分佈式hdfs3.0,如何動態擴展hdfs節點、如何使用hdfs3.0的糾刪碼容錯等等。不當之處,請大家發郵件aishuc@126com給艾叔,謝謝!
本節我們將演示如何使用hdfs3.0的糾刪碼功能,糾刪碼是hdfs3.0新加入的功能,之前的hdfs都是採用副本方式容錯,默認情況下,一個文件有3個副本,可以容忍任意2個副本(datanode)不可用,這樣提高了數據的可用性,但也帶來了2倍的冗餘開銷。例如3TB的空間,只能存儲1TB的有效數據。而糾刪碼則可以在同等可用性的情況下,節省更多的空間,以rs-6-3-1024K這種糾刪碼策略爲例子,6份原始數據,編碼後生成3份校驗數據,一共9份數據,只要最終有6份數據存在,就可以得到原始數據,它可以容忍任意3份數據不可用,而冗餘的空間只有原始空間的0.5倍,只有副本方式的1/4,因此,可以大大節約成本。
由於編碼出來的數據,要分佈到多臺datanode上,例如rs-6-3-1024K,就需要至少6+3=9臺datanode,我們目前只有2個datanode,因此還需要擴充7個datanode。下面的的操作就是,先擴充datanode,然後演示如何進行糾刪碼操作。
6.1 複製datanode節點、並動態加入
由於糾刪碼要用到多個節點,我們複製dn1,構建10個datanode,分佈從dn2~dn9,每個datanode的內存配置爲256MB。IP地址從192.168.182.13~192.168.182.20。
A. 每個datanode上要做的事情:
1. 修改虛擬機名、主機名
2. 修改網絡配置
3. 添加hosts解析
4. 清除datanode存儲目錄下的文件
5. 虛擬機內存調整位256MB
注意:打開虛擬機時,一定要選擇“I copied it”
B. 在nn1上要做的事情:
1. 添加hosts解析
2. workers文件中添加所有的datanode主機名
C. 在dn1上要做的事情:
1. 添加hosts解析
這是最終啓動的虛擬機nn1,dn1~dn9
6-1 hdfs3.0糾刪碼演示環境虛擬機
每個datanode的內存是256MB
6-2 Vmware workstation虛擬機內存配置
每個節點的hosts文件
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.182.11 nn1
192.168.182.12 dn1
192.168.182.13 dn2
192.168.182.14 dn3
192.168.182.15 dn4
192.168.182.16 dn5
192.168.182.17 dn6
192.168.182.18 dn7
192.168.182.19 dn8
192.168.182.20 dn9
動態加入後的hdfs3.0如下
6-3 hdfs3.0 web信息界面
6.2 糾刪碼基本操作
1. 查看當前支持的糾刪碼策略
命令如下
[user@nn1 ~]$ hdfs ec -listPolicies
Erasure Coding Policies:
ErasureCodingPolicy=[Name=RS-10-4-1024k, Schema=[ECSchema=[Codec=rs, numDataUnits=10, numParityUnits=4]], CellSize=1048576, Id=5, State=DISABLED]
ErasureCodingPolicy=[Name=RS-3-2-1024k, Schema=[ECSchema=[Codec=rs, numDataUnits=3, numParityUnits=2]], CellSize=1048576, Id=2, State=DISABLED]
ErasureCodingPolicy=[Name=RS-6-3-1024k, Schema=[ECSchema=[Codec=rs, numDataUnits=6, numParityUnits=3]], CellSize=1048576, Id=1, State=DISABLED]
ErasureCodingPolicy=[Name=RS-LEGACY-6-3-1024k, Schema=[ECSchema=[Codec=rs-legacy, numDataUnits=6, numParityUnits=3]], CellSize=1048576, Id=3, State=DISABLED]
ErasureCodingPolicy=[Name=XOR-2-1-1024k, Schema=[ECSchema=[Codec=xor, numDataUnits=2, numParityUnits=1]], CellSize=1048576, Id=4, State=DISABLED]
目前hadoop-3.0.0beta1共支持5種糾刪碼策略,分別是:
RS-10-4-1024k:使用RS編碼,每10個數據單元(cell),生成4個校驗單元,共14個單元,也就是說:這14個單元中,只要有任意的10個單元存在(不管是數據單元還是校驗單元,只要總數=10),就可以得到原始數據。每個單元的大小是1024k=1024*1024=1048576。
RS-3-2-1024k:使用RS編碼,每3個數據單元,生成2個校驗單元,共5個單元,也就是說:這5個單元中,只要有任意的3個單元存在(不管是數據單元還是校驗單元,只要總數=3),就可以得到原始數據。每個單元的大小是1024k=1024*1024=1048576。
RS-6-3-1024k:使用RS編碼,每6個數據單元,生成3個校驗單元,共9個單元,也就是說:這9個單元中,只要有任意的6個單元存在(不管是數據單元還是校驗單元,只要總數=6),就可以得到原始數據。每個單元的大小是1024k=1024*1024=1048576。
RS-LEGACY-6-3-1024k:策略和上面的RS-6-3-1024k一樣,只是編碼的算法用的是rs-legacy,應該是之前遺留的rs算法。
XOR-2-1-1024k:使用XOR編碼(速度比RS編碼快),每2個數據單元,生成1個校驗單元,共3個單元,也就是說:這3個單元中,只要有任意的2個單元存在(不管是數據單元還是校驗單元,只要總數=2),就可以得到原始數據。每個單元的大小是1024k=1024*1024=1048576。
以RS-6-3-1024k爲例,6個數據單元+3個校驗單元,可以容忍任意的3個單元丟失,冗餘的數據是50%。而採用副本方式,3個副本,冗餘200%,卻還不能容忍任意的3個單元丟失。因此,RS編碼在相同冗餘度的情況下,會大大提升數據的可用性,而在相同可用性的情況下,會大大節省冗餘空間。
2. 設置糾刪碼策略
糾刪碼策略是與具體的路徑(path)相關聯的。也就是說,如果我們要使用糾刪碼,則要給一個具體的路徑設置糾刪碼策略,後續,所有往此目錄下存儲的文件,都會執行此策略。
例子如下
首先在/下創建目錄rs-6-3,然後查看其是否設置了糾刪碼策略,結果顯示沒有指定策略(新建的目錄不會指定策略)
[user@nn1 ~]$ hdfs dfs -mkdir /rs-6-3
[user@nn1 ~]$ hdfs ec -getPolicy -path /rs-6-3
The erasure coding policy of /rs-6-3 is unspecified
接下來,給此目錄設置糾刪碼策略RS-6-3-1024k,此策略名是從前面list策略中查到的。可以看到已經設置成功。
[user@nn1 ~]$ hdfs ec -setPolicy -path /rs-6-3 -policy RS-6-3-1024k
Set erasure coding policy RS-6-3-1024k on /rs-6-3
注意:
RS-6-3-1024k可以直接設置成功,其它的策略需要enable後,才能設置:
設置RS-3-2-1024k,這個需要先enablePolicy
[user@nn1 hadoop-3.0.0-beta1]$ hdfs ec -enablePolicy -policy RS-3-2-1024k
Erasure coding policy RS-3-2-1024k is enabled
[user@nn1 hadoop-3.0.0-beta1]$ hdfs ec -setPolicy -path /rs-3-2 -policy RS-3-2-1024k
Set erasure coding policy RS-3-2-1024k on /rs-3-2
驗證
[user@nn1 hadoop-3.0.0-beta1]$ hdfs ec -getPolicy -path /rs-3-2
RS-3-2-1024k
設置RS-10-4-1024k,如果不enablePolicy,會報錯
[user@nn1 hadoop-3.0.0-beta1]$ hdfs dfs -mkdir /rs-10-4
[user@nn1 hadoop-3.0.0-beta1]$ hdfs ec -setPolicy -path /rs-10-4 -policy RS-10-4-1024k
報錯了
RemoteException: Policy 'RS-10-4-1024k' does not match any enabled erasure coding policies: [RS-3-2-1024k, RS-6-3-1024k]. An erasure coding policy can be enabled by enableErasureCodingPolicy API.
3. 上傳文件,查看文件編碼情況
下面我們上傳一個文件看一下,這裏提示我們沒有使用ISA-L支持的編碼器(這個編碼器和CPU優化相結合,效率更高,需要重新編譯和配置,我們後續再講)
[user@nn1 ~]$ hdfs dfs -cp /profile /rs-6-3/
2017-11-30 10:24:29,620 WARN erasurecode.ErasureCodeNative: ISA-L support is not available in your platform... using builtin-java codec where applicable
查看profile編碼後的分佈
[user@nn1 ~]$ hdfs fsck /rs-6-3/profile -files -blocks -locations
輸出
Connecting to namenode via http://nn1:9870/fsck?ugi=user&files=1&blocks=1&locations=1&path=%2Frs-6-3%2Fprofile
FSCK started by user (auth:SIMPLE) from /192.168.182.11 for path /rs-6-3/profile at Thu Nov 30 10:57:12 EST 2017
/rs-6-3/profile 1872 bytes, erasure-coded: policy=RS-6-3-1024k, 1 block(s): OK
0. BP-529485104-192.168.182.11-1511810134643:blk_-9223372036854775792_1065 len=1872 Live_repl=4 [blk_-9223372036854775792:DatanodeInfoWithStorage[192.168.182.11:9866,DS-da58ee3e-adcc-4f6c-8488-c2a0b742d8b9,DISK], blk_-9223372036854775786:DatanodeInfoWithStorage[192.168.182.20:9866,DS-c36de658-0f5a-42de-8898-eab3b04c7016,DISK], blk_-9223372036854775785:DatanodeInfoWithStorage[192.168.182.14:9866,DS-a3569982-de52-42b5-8543-94578f8b452a,DISK], blk_-9223372036854775784:DatanodeInfoWithStorage[192.168.182.19:9866,DS-71be9468-c0c7-437c-8b59-ece27593b4c2,DISK]]
查看block文件的信息,可以看到nn1上block的大小正好是1872。這是因爲1872<1024k,因此無法分割,直接整體編碼。
[user@nn1 ~]$ ls dfs/share/datanode/current/BP-529485104-192.168.182.11-1511810134643/current/finalized/subdir0/subdir0/blk_-9223372036854775792 -l
-rw-rw-r--. 1 user user 1872 Nov 30 10:24 dfs/share/datanode/current/BP-529485104-192.168.182.11-1511810134643/current/finalized/subdir0/subdir0/blk_-9223372036854775792
Live_repl=4的解釋,表示此文件共有4個副本,其中1個是原始數據,3個是校驗數據,因此,這裏的策略是rs_6_3,要保證冗餘3個校驗單元,原始數據1872<1024k,只能構成1個數據單元,再加上3個校驗單元,就是4個副本了。
1 block(s)的解釋:blocks是指數據單元在datanode的存儲而言,1872<1024k,只有1個數據單元,因此只能分配到1個datanode,對於每個datanode,其block默認大小是256MB(hdfs3.0是256MB,hdfs2.x是128MB),1872遠小於256MB,當然只有1個block了,如果單個datanode上多個數據單元之和>256MB,這時纔會生成新的block。
再看一個
hdfs dfs -cp file:///home/user/jdk1.8.0_152/lib/ant-javafx.jar /rs-6-3/
此文件的大小是1224175>1024k,但是<2*1024k,也就是可以構成2個數據單元,加上3個校驗單元,推測最終編碼出來一共是5個副本。
查看下
[user@nn1 ~]$ hdfs fsck /rs-6-3/ant-javafx.jar -files -blocks -locations
果然是
/rs-6-3/ant-javafx.jar 1224175 bytes, erasure-coded: policy=RS-6-3-1024k, 1 block(s): OK
0. BP-529485104-192.168.182.11-1511810134643:blk_-9223372036854775776_1066 len=1224175 Live_repl=5 [blk_-9223372036854775776:DatanodeInfoWithStorage[192.168.182.11:9866,DS-da58ee3e-adcc-4f6c-8488-c2a0b742d8b9,DISK], blk_-9223372036854775775:DatanodeInfoWithStorage[192.168.182.18:9866,DS-2dc5d603-ad42-4558-bfda-c9a597f88f06,DISK], blk_-9223372036854775770:DatanodeInfoWithStorage[192.168.182.14:9866,DS-a3569982-de52-42b5-8543-94578f8b452a,DISK], blk_-9223372036854775769:DatanodeInfoWithStorage[192.168.182.20:9866,DS-c36de658-0f5a-42de-8898-eab3b04c7016,DISK], blk_-9223372036854775768:DatanodeInfoWithStorage[192.168.182.13:9866,DS-118ae8da-f820-447c-9d97-dbe4f33bff39,DISK]]
查看第一個block的大小(nn1),可以看到正好是按照1024k來切分的
[user@nn1 ~]$ ls dfs/share/datanode/current/BP-529485104-192.168.182.11-1511810134643/current/finalized/subdir0/subdir0/blk_-9223372036854775776 -l
-rw-rw-r--. 1 user user 1048576 Nov 30 10:30 dfs/share/datanode/current/BP-529485104-192.168.182.11-1511810134643/current/finalized/subdir0/subdir0/blk_-9223372036854775776
查看第二個block的大小(nn7),其大小是175599
[user@dn7 ~]$ ls dfs/share/datanode/current/BP-529485104-192.168.182.11-1511810134643/current/finalized/subdir0/subdir0/blk_-9223372036854775775 -l
-rw-rw-r--. 1 user user 175599 Nov 30 11:54 dfs/share/datanode/current/BP-529485104-192.168.182.11-1511810134643/current/finalized/subdir0/subdir0/blk_-9223372036854775775
第一個block 1048576 + 第二個block 175599 = 1224175,正好是ant-javafx.jar的大小。
爲什麼第二個block沒有補齊1024k呢?因爲補齊的話,也是填0,沒有必要。
第三個block~第五個block是校驗數據。
4. 數據恢復驗證(datanode dead的時間間隔是10m)
我們以ant-javafx.jar爲例,它有5個副本,分佈在:
192.168.182.11
192.168.182.18
192.168.182.14
192.168.182.20
192.168.182.13
其中2個原始數據單元、3個校驗數據單元,意味着可以容忍任意3個數據單元的丟失。
下面,我們關閉後3個節點上的datanode
192.168.182.14
192.168.182.20
192.168.182.13
然後從/rs-6-3目錄中複製ant-javafx.jar到本地/tmp目錄,並和本地的ant-javafx.jar比較,正確,說明數據沒有問題。
[user@nn1 ~]$ hdfs dfs -cp /rs-6-3/ant-javafx.jar file:///tmp/
2017-11-30 13:12:36,493 WARN erasurecode.ErasureCodeNative: ISA-L support is not available in your platform... using builtin-java codec where applicable
[user@nn1 ~]$ diff jdk1.8.0_152/lib/ant-javafx.jar /tmp/ant-javafx.jar
再關掉一個節點,在下面的節點
192.168.182.18
運行
[user@dn7 ~]$ hdfs --daemon stop datanode
在nn1上再次複製
報錯,因爲丟失的數據單元個數>3了
cp: 4 missing blocks, the stripe is: Offset=0, length=175599, fetchedChunksNum=0, missingChunksNum=4
在dn3上啓動datanode,再次複製
發現還是報錯,說192.168.182.18上數據丟失,這是爲什麼呢?
查看HDFS狀態,發現剛纔關閉的dn3 dn9 dn2 dn7仍然是live的,這是因爲datanode的狀態有一個刷新的間隔,這個間隔默認是10m(600s),只有10m沒有收到datanode的消息,namenode才認爲此datanode是dead的。
因此,等待10m後,可以看到HDFS的live nodes變成了7
6-4 hdfs3.0 web datanode信息界面
這個時候,再次複製,DFSClient就知道dn7是dead,就不會再選擇dn7了,轉而選擇其它的live節點,因此複製成功。
[user@nn1 ~]$ hdfs dfs -cp /rs-6-3/ant-javafx.jar file:///tmp/
2017-11-30 13:26:35,241 WARN erasurecode.ErasureCodeNative: ISA-L support is not available in your platform... using builtin-java codec where applicable
cp: `file:///tmp/ant-javafx.jar': File exists
將dn2、dn7、dn9恢復,啓動datanode,再次查看
[user@nn1 ~]$ hdfs fsck /rs-6-3/ant-javafx.jar -files -blocks -locations
Connecting to namenode via http://nn1:9870/fsck?ugi=user&files=1&blocks=1&locations=1&path=%2Frs-6-3%2Fant-javafx.jar
FSCK started by user (auth:SIMPLE) from /192.168.182.11 for path /rs-6-3/ant-javafx.jar at Thu Nov 30 13:29:30 EST 2017
/rs-6-3/ant-javafx.jar 1224175 bytes, erasure-coded: policy=RS-6-3-1024k, 1 block(s): OK
0. BP-529485104-192.168.182.11-1511810134643:blk_-9223372036854775776_1066 len=1224175 Live_repl=5 [blk_-9223372036854775776:DatanodeInfoWithStorage[192.168.182.11:9866,DS-da58ee3e-adcc-4f6c-8488-c2a0b742d8b9,DISK], blk_-9223372036854775770:DatanodeInfoWithStorage[192.168.182.14:9866,DS-a3569982-de52-42b5-8543-94578f8b452a,DISK], blk_-9223372036854775769:DatanodeInfoWithStorage[192.168.182.19:9866,DS-71be9468-c0c7-437c-8b59-ece27593b4c2,DISK], blk_-9223372036854775768:DatanodeInfoWithStorage[192.168.182.16:9866,DS-c32fdd4e-aa34-4b65-b192-643ade06d71b,DISK], blk_-9223372036854775775:DatanodeInfoWithStorage[192.168.182.18:9866,DS-2dc5d603-ad42-4558-bfda-c9a597f88f06,DISK]]
發現數據單元的分佈發生了變化
192.168.182.11
192.168.182.14
192.168.182.19
192.168.182.16
192.168.182.18
其中綠色部分,應該是在這些節點關閉後,hdfs重新啓動譯碼和編碼,將原來丟失的數據補到了dn8和dn5上。而dn8沒有去掉,可能是還沒來得及。
總之,如果編碼後的stripe中,有數據丟失,hdfs會自動啓動恢復工作。
上一篇:《hadoop-3.0.0-beta1運維手冊(010):hdfs3.0.0基本操作-hdfs動態加入節點(2)》
原創文章,轉載請註明: 轉載自大數據學習網,作者:艾叔