【背景】
前段时间在HDFS的dn节点规模1000+的环境中,并且有1亿block数据量的情况下, 进行大量并发写文件测试时,发现部分客户端写异常并导致最终仅写入了部分数据,本文就该问题进行分析总结。
【表面现象分析】
出现该问题时,首先查看了客户端的日志,发现这些客户端的日志中,都出现了NotReplicatedYetException的告警日志,其他全部成功写入的客户端中有的也有这样的日志。
既然都出现了这个告警日志,那为什么有的能全部成功写入,有的就直接退出不写了呢?
这个现象背后的原理其实很简单:当客户端写文件过程中,向nn发送申请新的block的rpc请求时,如果nn以错误形式返回NotReplicatedYetException,客户端的rpc处理会根据该错误构造对应的异常并向上抛出异常,接口调用的处理中又会捕获该异常,然后睡眠一段时间,并再次发送申请block的rpc请求。当重试到达一定次数后,仍旧是失败的,那么就不再继续尝试,直接退出。
关键代码如下:
protected LocatedBlock locateFollowingBlock(DatanodeInfo[] excluded,
ExtendedBlock oldBlock) throws IOException {
final DfsClientConf conf = dfsClient.getConf();
// 默认5次
int retries = conf.getNumBlockWriteLocateFollowingRetry();
// 首次重试睡眠时间为 400ms
long sleeptime = conf.getBlockWriteLocateFollowingInitialDelayMs();
while (true) {
long localstart = Time.monotonicNow();
while (true) {
try {
return dfsClient.namenode.addBlock(src, dfsClient.clientName,
oldBlock, excluded, stat.getFileId(), favoredNodes,
addBlockFlags);
} catch (RemoteException e) {
IOException ue =
e.unwrapRemoteException(FileNotFoundExcept