Hadoop(十)Hadoop IO之數據完整性
前言
上一篇我分享了Hadoop的壓縮和編解碼器,在我們開發的過程中其實是經常會用到的,所以一定要去掌握。這一篇給大家介紹的是Hadoop的數據完整性!
Hadoop用戶在使用HDFS儲存和處理數據不會丟失或者損壞,在磁盤或者網絡上的每一個I/O操作不太可能將錯誤引入自己正在讀/寫的數據中,但是如果
在處理的數據量非常大到Hadoop的處理極限時,數據被損壞的概率還是挺大的。
一、數據完整性概述
檢測數據是否損壞的常用措施是:在數據第一次引入系統時計算校驗和並在數據通過一個不可靠的同道進行傳輸時再一次計算校驗和,這樣就能發現數據是否
損壞。如果計算所得的新校驗和原來的校驗不匹配,那麽表明數據已經損壞
註意:該技術並不能修復數據,它只能檢測出數據錯誤。(校驗和數據也可能損壞,但是由於校驗和文件小,所以損壞的可能性小)
常用的錯誤檢測碼是:CRC-32(循環冗余校驗),使用CRC-32算法任何大小的數據輸入均計算得到一個32位的整數校驗碼。
二、HDFS的數據完整性
2.1、本地文件上傳到HDFS集群時的校驗
下面我畫了一個圖好理解:
比如說我們要本地的passwd文件上傳到HDFS集群中,會在本地通過CRC-32算法產生一個對passwd文件的一個校驗文件:.passwd.crc。在我們將passwd上傳到HDFS集群的時候,
會將本地文件系統中產生的.passwd.crc文件一起寫入到HDFS集群當中。在HDFS集群中接收到數據以後也會產生一個校驗文件和本地的校驗文件進行比較,如果相同則會存儲,
並且也會存儲本地的.passwd.crc文件到數據節點中。如果不相同則不存儲。
2.2、HDFS集群文件讀取到本地
這裏我就不畫圖了。
當我們客戶端要去讀取HDFS集群上的數據時,因為數據都是存儲在DataNode當中的,所以會NameNode會告訴客戶端去哪個數據塊中去尋找數據,找到之後存儲數據的DataNode會使用
CRC-32算法產生一個校驗文件和最開始寫入數據一起上傳上來的校驗文件進行對比。如果不相同說明數據已經損壞了,此時DataNode就會報告NameNode數據已經損壞了。這時候NameNode
就會告訴客戶端這個數據塊的數據不能用了,你去別的數據塊中去尋找數據,這樣客戶端就能找到完整恩地數據。(對於損壞的數據,NameNode會重新去拷貝,進行重新的備份。)
三、涉及數據一致性的類:LocalFileSystem和RawFileSystem
3.1、概述
Hadoop的LocalFileSystem執行客戶端的校驗和驗證。當在你寫入一個filename的文件時,文件系統客戶端會明確地在包含每一個文件校驗和的同一個
目錄內新建一個名為.filename.crc的隱藏文件。
簡單的說:
當你把文件上傳到HDFS集群中時,你要對文件在本地進行CRC校驗就使用LocalFileSystem。
你不想對文件進行校驗時就是用RawFileSystem。
3.2、編寫程序驗證
我們知道LocalFileSystem和RawFileSystem都是FileSystem的子類
註意:這裏是在本地中對文件進行CRC檢驗。
1)DataIntegrity_Put_0010(上傳)
import java.io.OutputStream; import java.net.URI; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configured; import org.apache.hadoop.fs.FSDataOutputStream; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.LocalFileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.RawLocalFileSystem; import org.apache.hadoop.util.Tool; import org.apache.hadoop.util.ToolRunner; public class DataIntegrity_Put_0010 extends Configured implements Tool{ private FileSystem fs; private OutputStream os; @Override public int run(String[] args) throws Exception{ Configuration conf=getConf(); //不做數據校驗 fs=new RawLocalFileSystem(); //因為是直接new的對象,所以這裏使用這個方法去傳遞配置文件 fs.initialize(URI.create(args[0]),conf); os=fs.create(new Path(args[0])); os.write("123456".getBytes()); os.close(); //做數據校驗 fs=new LocalFileSystem(fs); os=fs.create(new Path(args[1])); os.write("09876".getBytes()); os.close(); return 0; } public static void main(String[] args) throws Exception{ System.exit( ToolRunner.run( new DataIntegrity_Put_0010(), args)); } }
測試:
在安裝了集群客戶端的Linux服務器中執行:
查看:沒有看到b.txt有校驗文件呀。因為它是隱藏文件
我們使用ls -l a查看隱藏文件:
對於a.txt因為使用的是RawFileSystem,所以沒有產生.a.txt.crc的校驗文件
對於b.txt
查看.a.txt.crc文件:它是一個二進制文件
以上就是我們將文件上傳到本地的文件系統時產生crc校驗文件,其實就是模擬了文件上傳到HDFS集群時的狀態。.
2)DataIntegrity_Get_0010(讀取)
import java.io.InputStream; import java.net.URI; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configured; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.LocalFileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.RawLocalFileSystem; import org.apache.hadoop.util.Tool; import org.apache.hadoop.util.ToolRunner; public class DataIntegrity_Get_0010 extends Configured implements Tool{ private FileSystem fs; private InputStream is; @Override public int run(String[] args) throws Exception{ Configuration conf=getConf(); fs=new RawLocalFileSystem(); fs.initialize(URI.create(args[0]),conf); is=fs.open(new Path(args[0])); byte[] buff=new byte[1024]; int len=is.read(buff); System.out.println(new String(buff,0,len)); is.close(); fs=new LocalFileSystem(fs); is=fs.open(new Path(args[1])); byte[] buff1=new byte[1024]; int len1=is.read(buff1); System.out.println(new String(buff1,0,len1)); is.close(); return 0; } public static void main(String[] args) throws Exception{ System.exit(ToolRunner.run(new DataIntegrity_Get_0010(),args)); } }
測試:
執行並產生結果:
當我們把沒有做校驗的a.txt修改一下:
再次運行程序是沒有問題的,顯示的是修改後的a.txt的數據。
當我們把做了校驗的b.txt修改一下:
再次運行程序:
結果:
喜歡就點個“推薦”!
Hadoop(十)Hadoop IO之數據完整性