當前位置:
首頁 > 知識 > hadoop源碼解析之hdfs內部結構分析

hadoop源碼解析之hdfs內部結構分析

http://zhangjun5965.iteye.com/blog/2377005


概述

hdfs的內部的文件和目錄是如何以樹的結構存儲的,每個文件對應的塊是如何存儲的,每個塊對應的怎麼對應到每一個datanode的,這些結構在hdfs的內部源碼是用哪些變數存儲的,整體結構是怎麼連接起來的,下面我們通過Hadoop的最新穩定版代碼(2.7.3)來學習一下。


命名空間Namesystem

org.apache.hadoop.hdfs.server.namenode.FSNamesystem類是hdfs的核心,存儲了hdfs的命名空間相關的很多東西,具體來說就是為DataNode做簿記工作,所有datanode的請求都經過FSNamesystem類來處理。

具體他做了哪些重要的工作,我們來看相關注釋

/***************************************************
* FSNamesystem does the actual bookkeeping work for the
* DataNode.
*
* It tracks several important tables.
*
文件名 -> 數據塊(存放在磁碟,也就是FSImage和日誌中)
* 1) valid fsname --> blocklist (kept on disk, logged)
合法的數據塊列表(上面關係的逆關係)
* 2) Set of all valid blocks (inverted #1)
數據塊 -> DataNode(只保存在內存中,根據DataNode發過來的信息動態建立)
* 3) block --> machinelist (kept in memory, rebuilt dynamically from reports)
DataNode上保存的數據塊(上面關係的逆關係)
* 4) machine --> blocklist (inverted #2)
通過LRU演算法保存最近發送過心跳信息的DataNode
* 5) LRU cache of updated-heartbeat machines
***************************************************/

文件目錄管理

/** The namespace tree. */
FSDirectory dir;
private final BlockManager blockManager;

在namenode中,對hdfs的目錄以及下面的子目錄、文件的操作相當的複雜,會涉及到內存、硬碟的相關操作,還需要和很多對象打交道,FSDirectory主要就是對這個內部的複雜的操作做了一個簡單的封裝,對外提供一個簡單的操作介面。

FSDirectory中很多重要的操作都和ClientProcotol協議中定義的相關方法一一對應,如addBlock等.

FSDirectory對象中有一個非常重要的INodeDirectory類型的變數rootDir,這個變數在內存中保存這個整個hdfs的目錄樹,下面我們對INode相關的知識做一下介紹。

i-node介紹linux i-node介紹

在Linux中,inode是一個非常重要的設計,具體我這裡就不介紹了,大家可以參考下這個文章。

hdfs的 INode介紹

org.apache.hadoop.hdfs.server.namenode.INode類是整個文件的一個抽象,其子類INodeDirectory和INodeFile分別表示目錄和相應的文件,我們來看下具體的類之間的關係

hadoop源碼解析之hdfs內部結構分析

其中,INode的直接子類INodeWithAdditionalFields存儲了一個文件或者目錄共有的一些東西,如id、名字、訪問許可權、訪問時間等

/** The inode id. */
final private long id;
/**
* The inode name is in java UTF8 encoding;
* The name in HdfsFileStatus should keep the same encoding as this.
* if this encoding is changed, implicitly getFileInfo and listStatus in
* clientProtocol are changed; The decoding at the client
* side should change accordingly.
*/
private byte name = null;
/**
* Permission encoded using {@link PermissionStatusFormat}.
* Codes other than {@link #clonePermissionStatus(INodeWithAdditionalFields)}
* and {@link #updatePermissionStatus(PermissionStatusFormat, long)}
* should not modify it.
*/
private long permission = 0L;
/** The last modification time*/
private long modificationTime = 0L;
/** The last access time*/
private long accessTime = 0L;

INodeFile

在INodeFile類的內部,有一個非常重要的變數blocks,以一個數組的的形式保存著這個文件對應的塊,具體的BlockInfoContiguous的相關信息將在下節來講述。

private BlockInfoContiguous blocks;

INodeDirectory

INodeDirectory重要就是表示的hdfs中的目錄樹,和其他文件系統類似,一個目錄最重要的就是他的子目錄,在該類中,用一個INode類型的集合變數children表示。

private List children = null;

塊管理

hdfs中所有塊的管理通過FSNamesystem中的BlockManager變數來管理,主要可以提供一些常用的的服務,比如通過blockid查詢塊,某一個塊位於哪個datanode等等

private final BlockManager blockManager;

BlockManager通過BlocksMap來存儲信息

private final Namesystem namesystem;

private final DatanodeManager datanodeManager;

/**
* Mapping: Block -> { BlockCollection, datanodes, self ref }
* Updated only in response to client-sent information.
*/
final BlocksMap blocksMap;

數據塊BlockInfoContiguous

接下來我們說說hdfs中塊的最重要的 一個類,這個類里最核心的變數是一個Object的數組triplets。

/**
* This array contains triplets of references. For each i-th storage, the
* block belongs to triplets[3*i] is the reference to the
* {@link DatanodeStorageInfo} and triplets[3*i+1] and triplets[3*i+2] are
* references to the previous and the next blocks, respectively, in the list
* of blocks belonging to this storage.
*
* Using previous and next in Object triplets is done instead of a
* {@link LinkedList} list to efficiently use memory. With LinkedList the cost
* per replica is 42 bytes (LinkedList#Entry object per replica) versus 16
* bytes using the triplets.
*/
private Object triplets;

/**
* Construct an entry for blocksmap
* @param replication the block"s replication factor
*/
public BlockInfoContiguous(short replication) {
this.triplets = new Object[3*replication];
this.bc = null;
}

我們通過代碼看到,object數組的長度就是3*replication(3乘以block的副本數),

triplets[i]:存儲DatanodeStorageInfo對象,Block所在的DataNode;

triplets[i+1]:存儲BlockInfoContiguous對象,該DataNode上該block前一個Block;

triplets[i+2]:存儲BlockInfoContiguous,該DataNode上該block後一個Block;

這樣通過存儲塊在DataNode上的上一個和下一個塊實現了一個雙向鏈表。就能快速的遍歷該datanode上的所有的block,其實就是一個linkedlist,但是按照注釋中的說法,要比linkedlist節省空間,對於hdfs這些一個巨大的文件系統來說,每個塊存儲多一點空間,整體上將會是巨大的開銷。

集群中所有的塊的管理

集群中所有的塊的管理通過BlockManager中BlocksMap類型的對象blocksMap來管理

BlocksMap通過GSet存儲映射

private GSet blocks;

GSet是自定義的一個set集合,如下代碼所示,E必須是K的子類

/**
* A {@link GSet} is set,
* which supports the {@link #get(Object)} operation.
* The {@link #get(Object)} operation uses a key to lookup an element.
*
* Null element is not supported.
*
* @param The type of the keys.
* @param The type of the elements, which must be a subclass of the keys.
*/
@InterfaceAudience.Private
public interface GSet extends Iterable

保存hdfs的塊的管理用的是GSet的子類LightWeightGSet.


DatanodeStorageInfo 數據節點存儲

在介紹BlockInfoContiguous的時候,我們知道object數組第一項存儲的是該塊所在的datanode信息,即DatanodeStorageInfo類型的對象。

/**
* A Datanode has one or more storages. A storage in the Datanode is represented
* by this class.
*/
public class DatanodeStorageInfo{
........................

private final DatanodeDescriptor dn;
private final String storageID;
private StorageType storageType; //存儲類型,disk,ssd等
private State state;

private long capacity;
private long dfsUsed;
private volatile long remaining;
private long blockPoolUsed;

private volatile BlockInfoContiguous blockList = null;
private int numBlocks = 0;

// The ID of the last full block report which updated this storage.
private long lastBlockReportId = 0;

/** The number of block reports received */
private int blockReportCount = 0;

..............................

}

通過注釋,我們了解到一個datanode有不止一個存儲,該類所表示的是datanode相關的存儲信息。

其中DatanodeDescriptor對象是namenode對datanode的抽象,裡面封裝了一些datanode基本信息.

hadoop源碼解析之hdfs內部結構分析

DatanodeDescriptor相關的類的繼承關係如上圖,DatanodeID封裝了datanode相關的一些基本信息,如ip,host等。

private String ipAddr; // IP address
private String hostName; // hostname claimed by datanode
private String peerHostName; // hostname from the actual connection
private int xferPort; // data streaming port
private int infoPort; // info server port
private int infoSecurePort; // info server port
private int ipcPort; // IPC server port
private String xferAddr;

總結

通過上面的學習,我們基本捋請了整個hdfs的目錄和文件是如何存儲的,每個文件包含了哪些數據塊,每個數據塊存儲在哪個datanode上,具體的host和port是多少。

還簡單了解了下hdfs是如何通過blockmanage來管理hdfs中所有的數據塊

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 達人科技 的精彩文章:

圖像工具包VintaSoftImaging.NET SDK v8.5,新增獨立web服務
UIDebuggingInformationOverlay在OC語法中使用
使用 zabbix 自動發現監控 MySQL

TAG:達人科技 |

您可能感興趣

AtomicInteger 源碼解析
Photoshop詳細解析CameraRaw插件使用
Android項目解耦-路由框架ARouter源碼解析
druid-spring-boot-starter源碼解析
Istio技術與實踐02:源碼解析之Istio on Kubernetes 統一服務發現
Google研究員解析Anthos和開源戰略
筆尖星球之Android文件管理神器:Handshaker新增亮點解析
網關 Spring-Cloud-Gateway 源碼解析——路由之RouteDefinitionLocator一覽
Android Studio項目模板全面解析
精讀解析 《When Sophie Gets Angry》
osg例子解析-osgsimpleshaders
hbase查詢解析
深度解析政府監聽工具FinFisher:Windows
Google研究員深入解析Anthos和開源戰略
Google 開源 robots.txt 解析器,推動 REP 標準化
長文解析:Gardenscapes的成功和Playrix的轉型分析
Ansible 深度解析
藉助Jackson的JsonTypeInfo註解實現多態類的解析
Photoshop詳細解析套索工具的摳圖技巧
SparseArray 稀疏數組解析