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分別表示目錄和相應的文件,我們來看下具體的類之間的關係
其中,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
塊管理
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
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
* @param
*/
@InterfaceAudience.Private
public interface GSet
保存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基本信息.
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 稀疏數組解析