Hadoop權威指南---HDFS簡介和java API操作
目錄
Hadoop分散式檔案系統
1、HDFS的設計
HDFS的特點
- 超大檔案,目前已經有PB級資料的Hadoop叢集;
- 流式資料訪問,一次寫入、多次讀取;
- 運作在普通的硬體上;
- 不適合底時間延遲的資料訪問,hbase基於記憶體的資料庫,可以滿足低延時的訪問;
- 不適合大量的小檔案,namenode的限制;
- 只支援單使用者寫入,而且不支援修改,支援在檔案的末尾追加;
2、 HDFS的概念
2.1 資料塊
一般情況下,塊的大小,太大或者太小都不好;
使用塊結果儲存資料的三個好處:
- 檔案的大小不在侷限於磁碟的大小,把大檔案拆分成塊,分別進行儲存;
- 檔案的元資料資訊和資料資訊分開管理;
- 塊資料更加容易實現容錯和可用性;
2.2 namenode和datanode 概述
2.3 塊快取
2.4 聯邦HDFS
2.5 HDFS的高可用性
Hadoop2的HA是通過一個active namenode節點、一個standby namenode節點和一個共享編輯日誌的檔案系統(常用的是zookeeper)來實現的。這裡的standby namenode節點還具有之前secondary namenode節點定期合併映象和編輯日誌的功能。
同時需要注意在切換的時候需要保證只有一個節點作為主節點在對外提供服務,避免同時出現兩個namenode編輯日誌,也就是規避,避免“腦裂”---多主的情況;
恢復名稱空間的流程:
3、 命令列介面
Hadoop fs 引數 路徑
4、 Hadoop檔案系統分類
5、Java介面API
hdfs的java API常見操作歸類 對檔案的增刪改查(注意:HDFS的檔案不能修改,而只能在現有的檔案中追加或者新建檔案)DistributedFileSystem類的方法
5.1、增:建立檔案create和write、資料夾mkdirs
FSDataOutputStream create(Path f)
5.2、刪:刪除資料夾和檔案delete
delete方法可以用來遞迴刪除某個目錄下的檔案資訊,因此path可以是具體的檔案路徑或者目錄路徑 boolean delete(Path f, boolean recursive) 如果f是一個檔案或者空目錄,那麼recursive的值就會被忽略;只有recursive值為true時,非空目錄及其內容才會被刪除。
5.3、改:追加append
FSDataOutputStream append(Path f)
FSDataOutputStream append(Path f, int bufferSize)
FSDataOutputStream append(Path var1, int var2, Progressable var3)
5.4、查:檢視檔案和資料夾open和read
這裡分兩部分:獲取檔案的元資料資訊和獲取檔案的資料資訊
5.4.1、獲取檔案的元資料資訊listFiles、listStatus以及globStatus
檔案元資料的封裝類FileStatus
public class FileStatus implements Writable, Comparable {
private Path path; 路徑
private long length; 長度
private boolean isdir; 是不是目錄
private short block_replication; 檔案塊的備份數
private long blocksize; 檔案塊的大小
private long modification_time; 修改時間
private long access_time; 訪問時間???
private FsPermission permission; 許可權
private String owner; 所屬者
private String group; 所屬組
private Path symlink; 檔案型別,判斷是不是連結的檔案型別
...
}
其中LocatedFileStatus在FileStatus基礎上擴充套件了一個欄位locations,用於描述該檔案的資料塊的儲存位置
public class LocatedFileStatus extends FileStatus {
private BlockLocation[] locations; 檔案的資料塊的儲存位置
...
}
public class BlockLocation {
private String[] hosts; block所在的伺服器
private String[] cachedHosts; block的cachehosts
private String[] names; 塊的名字
private String[] topologyPaths;
private long offset; 檔案開始偏移量
private long length; 列印block的大小
private boolean corrupt;
private static final String[] EMPTY_STR_ARRAY = new String[0];
...
}
只列出路徑下的檔案而不列出資料夾listFiles RemoteIterator<LocatedFileStatus> listFiles(final Path f, final boolean recursive)
即列出檔案又列出資料夾listStatus FileStatus[] listStatus(Path var1) FileStatus[] listStatus(Path f, PathFilter filter) FileStatus[] listStatus(Path[] files) FileStatus[] listStatus(Path[] files, PathFilter filter)
通過萬用字元(正則表示式)來匹配路徑globStatus FileStatus[] globStatus(Path pathPattern) FileStatus[] globStatus(Path pathPattern, PathFilter filter) PathFilter 是用來限制匹配的檔案和目錄 public interface PathFilter { boolean accept(Path var1); } 通過實現這個介面,開自定義排除指定路徑
demo1:listFiles例項
/**
為什麼使用RemoteIterator<LocatedFileStatus>,這是一個遠端的迭代器,由於HDFS伺服器資料量比較多,
不能一次性返回所有檔案資訊(可能撐爆記憶體),所以一邊迭代一邊從遠端伺服器上獲取。分治的思想。
*/
//列印檔案列表
public static void listfiles(FileSystem fileSystem) throws Exception, IOException {
RemoteIterator<LocatedFileStatus> fileLists = fileSystem.listFiles(new Path("/"), true);
while (fileLists.hasNext()) {
LocatedFileStatus locatedFileStatus = fileLists.next();
// 按照以下格式列印HDFS上的檔案資訊
// drwxr-xr-x - root supergroup 0 2015-12-18 00:24 /itcast/hadoop
String fileType = "-";
System.out.print(fileType);//但因檔案的型別
String authority = locatedFileStatus.getPermission().toString();
System.out.print(authority + "\t");//列印檔案的許可權
String user = locatedFileStatus.getOwner();
System.out.print(user + "\t");//列印檔案所屬的的使用者
long size = locatedFileStatus.getLen();
System.out.print(size + "\t");//列印檔案的大小
long date = locatedFileStatus.getModificationTime();
System.out.print(date + "\t");//列印檔案的時間戳
String path = locatedFileStatus.getPath().toString();
System.out.print(path + "\t");//列印檔案的路徑
System.out.println();
for (BlockLocation blockLocation : locatedFileStatus.getBlockLocations()) {
System.out.print("cacheHosts: ");
for (String hosts : blockLocation.getCachedHosts()) {
System.out.print(hosts + ",");//列印block的cachehosts
}
System.out.println();
System.out.print("hosts: ");
for (String hosts : blockLocation.getHosts()) {
System.out.print(hosts + ",");//列印檔案block所在的伺服器
}
System.out.println();
System.out.print("block size: ");
System.out.println(blockLocation.getLength());//列印block的大小
System.out.print("block start offset: ");
System.out.println(blockLocation.getOffset()); //檔案開始偏移量
System.out.println("----------------------------------------------");
}
}
}
demo2:listStatus例項
//檢視HDFS的所有檔案資訊(使用遞迴演算法)
public static void fileAll(FileSystem fileSystem) throws Exception {
printContent(fileSystem,new Path("/"));
}
public static void printContent(FileSystem fileSystem,Path path) throws Exception {
FileStatus[] fileStatuses = fileSystem.listStatus(path);
for (FileStatus fileStatus : fileStatuses) {
String fileType = "d";
if (fileStatus.isFile()) {
fileType = "-";
} else if (fileStatus.isSymlink()) {
fileType = "l";
}
System.out.println(fileType + fileStatus.getPermission() + "\t" + fileStatus.getOwner() + "\t" + fileStatus.getLen() + "\t" + fileStatus.getModificationTime() + "\t" + fileStatus.getPath());
if (fileStatus.isDirectory()) {
printContent(fileSystem, fileStatus.getPath());
}
}
}
5.4.2、獲取檔案的資料資訊open和read
5.5、其他的一些常見操作
5.5.1、重新命名rename
rename方法可以用來移動檔案,也可以用來重新命名檔案。 boolean rename(Path var1, Path var2)
5.5.2、檔案的上傳
void copyFromLocalFile(Path src, Path dst) 本地檔案上傳到HDFS
5.5.3、檔案的下載
void copyToLocalFile(boolean delSrc, Path src, Path dst, boolean useRawLocalFileSystem) 把HDFS上的檔案下載到本地 四個引數的含義分別是:是否刪除HDFS叢集下的原始檔案、HDFS檔案地址、本地檔案地址、是否使用原生進行操作。
5.6、HDFS檔案的流式處理
直接從輸入流往輸出流寫資料,藉助於工具類實現
6、 資料流(重點)
6.1 剖析檔案讀取流程
通過網路節點的拓撲結構,可以快速判斷哪個datanode節點是距離客戶端最近的節點,然後讀取資料資訊。
6.2 剖析檔案寫入流程
6.3 資料一致模型
7、 通過distcp並行複製
參考:
《Hadoop權威指南.大資料的儲存與分析.第4版》---第3章 Hadoop分散式檔案系統