HDFS学习笔记【Datanode/FsDatasetImpl】

功能说明

  • 管理存储目录下的数据块和方法
    持有FSVolumnList对象
  • 对Datanode存储空间进行操作
    持有DataStorage对象
  • 维护Datanode上所有的块副本信息
    持有ReplicaMap对象

目录,块,副本?

ReplicaMap

结构为Map<String,Map<Long,ReplicaInfo>> map,块池(BlockPoolId)和数据块副本的映射关系。

这个信息是块池汇报的吗?

ReplicaInfo

描述DN上保存的数据块副本信息,对外提供了

  • getBlockFile()
    获取副本的数据块文件
  • getMetaFile()
    获取副本的校验文件
  • getVolume()
    获取副本存储目录的FSVolumeImpl对象
  • getStorageUuid()
    获取副本存储目录的StorageUuid信息
  • unlinkBlock()
    去除副本的链接信息,通过复制一份出来。

不同状态的副本,加载到ReplicaMap时ReplcaInfo对应不同的子类

  • ReplicaBeingWritten
    副本正在通过管道Pipeline写入
    ReplicaUnderRecovery
    副本正在恢复操作
    ReplicaWaittingToBeRecovered
    副本正在等待恢复
    FinalizedReplica
    副本已经写完成,并且提交

FsDatasetSpi

FsDatasetImpl的根接口包含Datanode上管理和操作数据块副本的接口。

  • 底层FSVolumnList以及DataStorage的方法
  • 操作数据块的方法
    getStoredBlock,getBlockInputStream,append,finalizeBlock等
  • 缓存相关操作
    cache,uncache
  • 操作块池的方法
    addBlockPool,shutdownBlockPool,deleteBlockPool
  • 数据块汇报的方法
    getStorageReports,getBlockReports,getCacheReport

块,缓存,存储

FsDataSetImpl

字段

  • datanode
  • datanodeStorage
  • storageMap
    目录对应DataStorage对象
  • volumes
  • volumeMap
    副本块相关的
  • cacheManager
    缓存相关的,数据块缓存到内存工具类
  • asyncDiskService

方法

  • 操作块FsDatasetImpl
  • 操作存储DataStorage
  • 操作数据块相关方法
  • 操作缓存的方法
  • 操作块池的方法
  • 数据块汇报的方法
  • 回收站相关的方法

获取块FsDataSetImpl方法

  • getVolumes
  • getVolume

获取DataStorage方法

  • getStorage
  • getVolumeInfoMap
    获取FsVolumeImpl对应的存储目录信息

这个信息是怎么放进去的?

获取数据块副本信息方法

获取复制块
FsDatasetImpl中volumeMap(ReplicaMap类型)记录了DN所有的块信息,(块池和块的映射关系)

  • 获取ReplicaInfo对象
  • 获取副本数据块文件的引用
    info.getBlockFile();
  • 构造Block对象并返回
    new Block(blkId,blockfile.length(),gs);

副本校验

  • DirectoryScanner.run()获取内存和磁盘不一致的引用
  • checkAndUpdate 同步状态
    同步、更新引用、标记损坏(长度不一致),修改时间戳.
    更新引用需要 BlockPoolSlice.resolveDuplicateReplicas来判断保存哪一个。
    损坏块需要报告给NN.

操作副本块方法

以下的方法全是Synchronized的

createTemporary

  • 平衡时,或者数据块复制时创建的。
  • BlockReceiver构造时创建
  • 其他读线程不可见

是不是tem目录下的内容,没有被加载到BlockPoolSlice

  • Datanode向该副本写数据

createTemporary实现

  • 检查内存中是否已经有该副本
  • 获取一个FsVolumeImpl存储该副本
    可以是根据空闲/轮询
  • 在该存储目录下创建tmp目录
  • 构造ReplicaInfo信息
    ReplicaInPipeline newReplicaInfo = new ReplicaInPipeline(b.getBlockId,b.getGS(),v,f.getParentFile());

createRbw

和createTemporary类似,只不过目录在rbw目录下
其他读线程可见

recoverRbw

恢复Rbw状态的副本

  • 停止之前的写入线程
  • 检查时间戳,更新时间戳
  • 丢弃没有ack的数据
    ack返回的是一个值,表示之前的确认了。

启动时调用吧?

convertTemporaryToRbw

副本数据块接收完成之后,需要move到Rbw目录下,才可以对读线程可见。

  • 检查时间戳,目录,长度等
  • 移动目录
  • 构造新的ReplicaInfo(ReplicaBeingWritten),在volumeMap中更新。

append

对FINALIZED状态的副本执行追加写操作。

  • 从缓存中移除该块
    保持一致性,缓存部分解释
  • 去掉硬链接
    升级存储快照时,为了节省空间,previous中和current之间存的是硬链接。
  • 文件和meta复制到RBW目录
  • 构造新的ReplicaInfo,在volumeMap中更新

recoverAppend

恢复失败的追加写,在BlockReceiver的构造方法中调用。调用完recoverAppend之后,数据流管道中所有副本的状态都恢复到RBW状态。

NN控制恢复吗?

  • 调用recoverCheck()
    如果副本是FINALIZED状态,那么调用append方法。
    如果副本是RBW状态,那么更新副本时间戳即可。
    副本如果在TEM目录下,其他线程不可见
  • 检查时间戳,长度
  • 如果副本处于写状态,更新写线程
    replica会保存副本的写线程,writer属性
  • 确认长度一致

recoverClose

Datanode写操作恢复时,DataXceiver的writeBlock中调用的。
除了调用者不同,实现基本相同。

BlockReceiver和DataXceiver做啥事情的?

finalizeBlock

用户提交数据块,Datanode完成数据块写操作并成功接收数据流管道下游的ack时,PacketResponder.run()方法调用finalizeBock()提交数据块。

  • 检查副本状态
    RUR直接转状态即可
  • 移动目录
    其他的状态需要FsVolumeImpl.addFinalizedBlock()移动目录
  • 更新replicaMap
    构造新的FinalizedReplica对象,更新FsDatasetImpl.volumeMap

unfinalizeBlock

删除TEMPORARY状态的副本

  • 检查副本状态
  • 删除数据块文件和校验和文件
  • volumeMap中移除副本的ReplicaInfo

invalidate

删除RBW状态和FINALIZED状态的副本

  • 判断是否短路读,短路读从内存中删除
  • 异步从磁盘删除文件
    FsDatasetAsyncDiskService

initReplicaRecovery

写文件时异常退出,没有正常关闭文件时,需要对最后一个快进行恢复操作,然后进行后续操作。

  • NN节点选择主恢复节点
    Namenode初始化块,选择主恢复节点控制数据块恢复流程。
    NN心跳携带LeaseRecovery指令
  • 主恢复节点选择状态
    主节点调用InterDatanodeProtocol接口和其他的Datanode通信
    initReplicaRcovery获取数据流中各个Datanode副本恢复信息,选取最好的副本状态
    updateReplicaUnderRecovery方法同步所有Datanode上副本恢复。

执行步骤:
1) 获取当前的节点副本信息
2) 如果副本有写线程,通知该线程
replicaInpipeline.stopwriter(xceiverStopTimeout);
3)判断恢复操作是否有效
4)构造RepliaUnderRecovery对象,放入volumeMap中。

目前缺的是调用顺序

updateReplicaUnderRecovery

主恢复节点调用InterDatanodeProtocol.initReplicaRecovery方法后,回复数数据流管道所有块的副本状态。找到最好的状态作为目标状态。优先选择FINALIZED,否则选择长度最短的。
主恢复节点对列表中所有datanode调用InterDatanodeProtocol.updateReplicaUnderRecovery同步副本状态。
1)检查副本是不是RUR状态
2)检查副本数据块文件和校验文件是否匹配
3)如果长度比目标长,那么截断数据文件,重新计算校验和
4)更新副本状态为Finalized状态,更新volumeMap

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值