关于数据块、副本的介绍,请参考文章《HDFS源码分析之数据块Block、副本Replica》。
一、数据块状态BlockUCState
数据块状态用枚举类BlockUCState来表示,代码如下:
/** * States, which a block can go through while it is under construction. * 状态,一个数据块在under construction(即构建)过程中所应有的状态 */ static public enum BlockUCState { /** * Block construction completed.<br> * The block has at least one {@link ReplicaState#FINALIZED} replica, * and is not going to be modified. * 数据块构建完成状态。这个数据块含有至少一个副本,并且不会被修改。 */ COMPLETE, /** * The block is under construction.<br> * It has been recently allocated for write or append. * 数据块处于构建状态下。它最近被分配,用于write或append。 */ UNDER_CONSTRUCTION, /** * The block is under recovery.<br> * When a file lease expires its last block may not be {@link #COMPLETE} * and needs to go through a recovery procedure, * which synchronizes the existing replicas contents. * 数据块处于恢复阶段状态。 * 当一个文件租约到期,它的最后一个数据块可能不是COMPLETE状态,并且需要经历一个恢复过程,它将同步存在的副本目录。 */ UNDER_RECOVERY, /** * The block is committed.<br> * The client reported that all bytes are written to data-nodes * with the given generation stamp and block length, but no * {@link ReplicaState#FINALIZED} * replicas has yet been reported by data-nodes themselves. * * 数据块已被提交状态 * 随着获取到给定的时间戳和数据块长度,客户端汇报所有的字节均已写入数据节点,但是还没有达到FINALIZED状态的副本尚未被数据节点汇报,。 */ COMMITTED; }名字节点NameNode内存中文件系统树中的数据块一共有四种状态,分别如下:
1、COMPLETE:数据块构建完成状态。这种状态下,这个数据块含有至少一个副本,并且不会被修改。
COMPLETE状态下,数据块的大小和时间戳均不会再发生变化,而且名字节点NameNode已经至少收到一个数据节点DataNode汇报的FINALIZED状态的副本。同时,该状态下的block会在NameNode内存中保存finalized状态副本replica的位置locations,而当文件的所有block都是COMPLETE状态的,文件才可以被关闭。
2、UNDER_CONSTRUCTION:数据块处于构建阶段状态下。它最近被分配,用于write或append。
UNDER_CONSTRUCTION状态下,文件刚刚被create,或者正在被append,此时的数据块正在被持续的写入,其大小和时间戳都是可以更改的,但是这种状态的下的数据块对于读是可见的,具体能读多少则是由客户端询问DataNode得知的,该block的所有副本replica接收到的数据大小都会大于等于这个可读的数据大小,这样,才能保证所有的副本replica均可用。
3、UNDER_RECOVERY:数据块处于恢复阶段状态。当一个文件租约到期,它的最后一个数据块可能不是COMPLETE状态,并且需要经历一个恢复过程,它将同步存在的副本目录。
当文件正在被写入时,客户端由于某种原因异常退出,正在被写入的最后一个数据块block处于UNDER_CONSTRUCTION状态下,客户端租约lease就可能超期,此时recovery和block都分别需要继续recovery,而处于recovery过程中的数据块block的状态就称为UNDER_RECOVERY。
4、COMMITTED:数据块已被提交状态。随着获取到给定的时间戳和数据块长度,客户端汇报所有的字节均已写入数据节点,但是还没有达到FINALIZED状态的副本尚未被数据节点汇报。
写文件过程中,每次写完一个数据块,申请另外一个数据块,或者当文件写入完毕而关闭时,都会将上一个数据块(关闭时为最后一个数据块)提交,即数据块状态从UNDER_CONSTRUCTION到COMMITTED,此时客户端通过流式数据管道已将全部数据发送给目标节点列表中的全部数据节点并收到确认的信号,但是NameNode尚未接收到任何一个DataNode汇报FINALIZED状态的副本replica。
二、数据块副本状态ReplicaState
数据块副本状态用枚举类ReplicaState来表示,代码如下:
/** * Block replica states, which it can go through while being constructed. * 数据块副本状态,数据块副本被构造过程中所应有的状态 */ static public enum ReplicaState { /** Replica is finalized. The state when replica is not modified. */ // 副本为完成状态,不会被修改的状态 FINALIZED(0), /** Replica is being written to. */ // 副本正在被写入状态 RBW(1), /** Replica is waiting to be recovered. */ // 副本正在等待被恢复状态 RWR(2), /** Replica is under recovery. */ // 副本处于恢复阶段状态 RUR(3), /** Temporary replica: created for replication and relocation only. */ // 仅为数据块复制而创建的临时副本状态 TEMPORARY(4); private final int value; private ReplicaState(int v) { value = v; } public int getValue() { return value; } public static ReplicaState getState(int v) { return ReplicaState.values()[v]; } /** Read from in */ public static ReplicaState read(DataInput in) throws IOException { return values()[in.readByte()]; } /** Write to out */ public void write(DataOutput out) throws IOException { out.writeByte(ordinal()); } }数据节点DataNode内存中数据块副本一共有五种状态,分别如下:
1、FINALIZED:副本为完成状态,不会被修改的状态;
FINALIZED状态下的副本,数据已被完全写入,数据块副本大小及时间戳均不会再发生变化。此时,就等着其所在数据节点DataNode进行数据块汇报,将该数据块副本汇报给名字节点NameNode。
2、RBW:副本正在被写入状态;
此时数据块副本刚刚被create或者append,还处于写状态下的管道流中,正在被写入。但是数据块副本内的数据对于读还是可见的。
3、RWR:副本正在等待被恢复状态;
如果一个数据节点DataNode挂掉并且重启之后,所有处于写状态RBW的副本replica都会被转换为RWR状态。RWR的replica不会出现在数据流管道中,结果就是等着Lease恢复。
4、RUR:副本处于恢复阶段状态;
数据块副本写入过程中,客户端异常退出,租约Lease过期后,租约Lease和数据块副本replica需要被恢复,处于恢复的状态称为RWR。
5、TEMPORARY:仅为数据块复制而创建的临时副本状态;
集群负载均衡,或者数据块副本数需要恢复到正常水平情况下数据节点之间进行数据块副本复制时,需要传输replica,此时的replica就处于TEMPORARY状态,和RBW不同的是,它对读是不可见的,DataNode如果重启直接删除处于TEMPORARY状态的replica。