前言
正如我在前面的文章中曾经写过,在HDFS中存在着两大关系模块,一个是文件与block数据块的关系,简称为第一关系,但是相比于第一个关系清晰的结构关系,HDFS的第二关系就没有这么简单了,第二关系自然是与数据节点相关,就是数据块与数据节点的映射关系,里面的有些过程的确是错综复杂的,这个也很好理解嘛,本身block块就很多,而且还有副本设置,然后一旦集群规模扩大,数据节点的数量也将会变大,如何处理此时的数据块与对应数据节点的映射就必然不是简单的事情了,所以这里有一点是比较特别的,随着系统的运行,数据节点与他所包含的块列表时动态建立起来的,相应的名字节点也需要通过心跳来获取信息,并不断更新元数据信息。同样在第二关系中,有诸多巧妙的设计,望读者在下面的阅读中细细体会
相关涉及类
数据块关系中涉及的基本类其实不是很多,见如下:
1.BlocksMap--数据块映射图类,保存了数据块到数据节点列表以及所属INode文件节点的映射关系,是非常重要的一个类.
2.BlocksMap.BlockInfo--BlocksMap的内部类,保存了block的数据信息类.
3.DatanodeDescriptor--数据节点类,是对数据节点的抽象,里面包含了许多与数据节点有关的变量信息.
4.DatanodeID和DatanodeInfo--数据节点基本类,是DatanodeDescriptor的父类,在这里定义了一个节点最基本的信息.
5.GSet以及LightWeightGSet--链表集合类,保存了blockInfo信息的集合类,采用了哈希存储的方式存储block数据块信息.
6.PendingReplicationBlocks和UnderReplicatedBlocks--副本相关类,其实这并不算是基本数据块关系结构中的部分,这是副本关系中涉及的类,因为与数据块有联系,放在这儿举个例子
7.FSNamesystem--命名系统类,他是一个非常大的类,里面的代码量多大5千多行,涉及了多个模块间的交互处理,其中副本相关的部分也有在这里操作的.
OK,下面开始主要内容的讲述.
BlocksMap
映射关系图类,首先这一定是类似于map这种数据类型的,所以肯定有类似于put(key,value),get(key)这样的操作,的确是这样,但是他并没有直接沿用hashMap这样的现成的类,而是自己实现了一个轻量级的集合类,什么叫做轻量级呢,与我们平常见的又有区别呢.先看BlocksMap的主要变量定义
/**
* This class maintains the map from a block to its metadata.
* block's metadata currently includes INode it belongs to and
* the datanodes that store the block.
*/
class BlocksMap {
/**
* Internal class for block metadata.
* blockMap内部类保存block信息元数据
*/
static class BlockInfo extends Block implements LightWeightGSet.LinkedElement {
...
}
/** Constant {@link LightWeightGSet} capacity. */
private final int capacity;
private GSet<Block, BlockInfo> blocks;
BlocksMap(int initialCapacity, float loadFactor) {
this.capacity = computeCapacity();
//用轻量级的GSet实现block与blockInfo的映射存储
this.blocks = new LightWeightGSet<Block, BlockInfo>(capacity);
}
....
在构造函数的上面就是这个图类,新定义的集合类型,GSet,看里面的变量关系,就很明了,从Block到BlockInfo的映射,其中注意到后者是前者的子类,所以在这里,HDFS构造了一个父类到子类的映射.于是我们要跑到GSet类下看看具体的定义声明
/**
* 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 <K> The type of the keys.
* @param <E> The type of the elements, which must be a subclass of the keys.
* 定义了特殊集合类GSet,能够通过key来寻找目标对象,也可以移除对象,对象类同时也是key的子类
*/
public interface GSet<K, E extends K> extends Iterable<E> {
/**
* @return The size of this set.
*/
int size();
boolean contains(K key);
E get(K key);
E put(E element);
E remove(K key);
}
答案的确是这样,定义的方法也是类似于map类的方法.OK,GSet的定义明白,但是这还不够,因为在构造函数,HDFS用的是他的子类LightWeightGSet,在此类的介绍文字中说,这是轻量级的集合类,可以低开销的实现元素的查找
/**
* A low memory footprint {@link GSet} implementation,
* which uses an array for storing the elements
* and linked lists for collision resolution.
*
* No rehash will be performed.
* Therefore, the internal array will never be resized.
*
* This class does not support null element.
*
* This class is not thread safe.
*
* @param <K> Key type for looking up the elements
* @param <E> Element type, which must be
* (1) a subclass of K, and
* (2) implementing {@link LinkedElement} interface.
* 轻量级的集合类,低内存的实现用于寻找对象类,不允许存储null类型,存储的类型必须为key的子类
* 在里面用了哈希算法做了映射,没有进行哈希重映射,因此大小不会调整
*/
public class LightWeightGSet<K, E extends K> implements GSet<K, E> {
看起来非常神秘哦,接下来看变量定义
public class LightWeightGSet<K, E extends K> implements GSet<K, E> {
/**
* Elements of {@link LightWeightGSet}.
*/
public static interface LinkedElement {
/** Set the next element. */
public void setNext(LinkedElement next);
/** Get the next element. */
public LinkedElement getNext();
}
public static final L