最近在hdfs写文件的时候发现一个问题,create写入正常,append写入报错,每次都能重现,代码示例如下:

        FileSystem fs = FileSystem.get(conf);
OutputStream out = fs.create(file);
IOUtils.copyBytes(in, out, 4096, true); //正常
out = fs.append(file);
IOUtils.copyBytes(in, out, 4096, true); //报错

通过hdfs fsck命令检查出问题的文件,发现只有一个副本,难道是因为这个?

看FileSystem.append执行过程:

org.apache.hadoop.fs.FileSystem

    public abstract FSDataOutputStream append(Path var1, int var2, Progressable var3) throws IOException;

实现类在这里:

org.apache.hadoop.hdfs.DistributedFileSystem

    public FSDataOutputStream append(Path f, final int bufferSize, final Progressable progress) throws IOException {
this.statistics.incrementWriteOps(1);
Path absF = this.fixRelativePart(f);
return (FSDataOutputStream)(new FileSystemLinkResolver<FSDataOutputStream>() {
public FSDataOutputStream doCall(Path p) throws IOException, UnresolvedLinkException {
return DistributedFileSystem.this.dfs.append(DistributedFileSystem.this.getPathName(p), bufferSize, progress, DistributedFileSystem.this.statistics);
} public FSDataOutputStream next(FileSystem fs, Path p) throws IOException {
return fs.append(p, bufferSize);
}
}).resolve(this, absF);
}

这里会调用DFSClient.append方法

org.apache.hadoop.hdfs.DFSClient

    private DFSOutputStream append(String src, int buffersize, Progressable progress) throws IOException {
this.checkOpen();
DFSOutputStream result = this.callAppend(src, buffersize, progress);
this.beginFileLease(result.getFileId(), result);
return result;
} private DFSOutputStream callAppend(String src, int buffersize, Progressable progress) throws IOException {
LocatedBlock lastBlock = null; try {
lastBlock = this.namenode.append(src, this.clientName);
} catch (RemoteException var6) {
throw var6.unwrapRemoteException(new Class[]{AccessControlException.class, FileNotFoundException.class, SafeModeException.class, DSQuotaExceededException.class, UnsupportedOperationException.class, UnresolvedPathException.class, SnapshotAccessControlException.class});
} HdfsFileStatus newStat = this.getFileInfo(src);
return DFSOutputStream.newStreamForAppend(this, src, buffersize, progress, lastBlock, newStat, this.dfsClientConf.createChecksum());
}

DFSClient.append最终会调用NameNodeRpcServer的append方法

org.apache.hadoop.hdfs.server.namenode.NameNodeRpcServer

    public LocatedBlock append(String src, String clientName) throws IOException {
this.checkNNStartup();
String clientMachine = getClientMachine();
if (stateChangeLog.isDebugEnabled()) {
stateChangeLog.debug("*DIR* NameNode.append: file " + src + " for " + clientName + " at " + clientMachine);
} this.namesystem.checkOperation(OperationCategory.WRITE);
LocatedBlock info = this.namesystem.appendFile(src, clientName, clientMachine);
this.metrics.incrFilesAppended();
return info;
}

这里调用到FSNamesystem.append

org.apache.hadoop.hdfs.server.namenode.FSNamesystem

    LocatedBlock appendFile(String src, String holder, String clientMachine) throws AccessControlException, SafeModeException,
...
lb = this.appendFileInt(src, holder, clientMachine, cacheEntry != null); private LocatedBlock appendFileInt(String srcArg, String holder, String clientMachine, boolean logRetryCache) throws
...
lb = this.appendFileInternal(pc, src, holder, clientMachine, logRetryCache); private LocatedBlock appendFileInternal(FSPermissionChecker pc, String src, String holder, String clientMachine, boolean logRetryCache) throws AccessControlException, UnresolvedLinkException, FileNotFoundException, IOException {
assert this.hasWriteLock(); INodesInPath iip = this.dir.getINodesInPath4Write(src);
INode inode = iip.getLastINode();
if (inode != null && inode.isDirectory()) {
throw new FileAlreadyExistsException("Cannot append to directory " + src + "; already exists as a directory.");
} else {
if (this.isPermissionEnabled) {
this.checkPathAccess(pc, src, FsAction.WRITE);
} try {
if (inode == null) {
throw new FileNotFoundException("failed to append to non-existent file " + src + " for client " + clientMachine);
} else {
INodeFile myFile = INodeFile.valueOf(inode, src, true);
BlockStoragePolicy lpPolicy = this.blockManager.getStoragePolicy("LAZY_PERSIST");
if (lpPolicy != null && lpPolicy.getId() == myFile.getStoragePolicyID()) {
throw new UnsupportedOperationException("Cannot append to lazy persist file " + src);
} else {
this.recoverLeaseInternal(myFile, src, holder, clientMachine, false);
myFile = INodeFile.valueOf(this.dir.getINode(src), src, true);
BlockInfo lastBlock = myFile.getLastBlock();
if (lastBlock != null && lastBlock.isComplete() && !this.getBlockManager().isSufficientlyReplicated(lastBlock)) {
throw new IOException("append: lastBlock=" + lastBlock + " of src=" + src + " is not sufficiently replicated yet.");
} else {
return this.prepareFileForWrite(src, iip, holder, clientMachine, true, logRetryCache);
}
}
}
} catch (IOException var11) {
NameNode.stateChangeLog.warn("DIR* NameSystem.append: " + var11.getMessage());
throw var11;
}
}
} public boolean isSufficientlyReplicated(BlockInfo b) {
int replication = Math.min(this.minReplication, this.getDatanodeManager().getNumLiveDataNodes());
return this.countNodes(b).liveReplicas() >= replication;
}

在append文件的时候,会首先取出这个文件最后一个block,然后会检查这个block是否满足副本要求,如果不满足就抛出异常,如果满足就准备写入;
看来原因确实是因为文件只有1个副本导致append报错,那为什么新建文件只有1个副本,后来找到原因是因为机架配置有问题导致的,详见 https://www.cnblogs.com/barneywill/p/10114504.html

【原创】大叔问题定位分享(20)hdfs文件create写入正常,append写入报错的更多相关文章

  1. 【报错】spring整合activeMQ,pom.xml文件缺架包,启动报错:Caused by: java.lang.ClassNotFoundException: org.apache.xbean.spring.context.v2.XBeanNamespaceHandler

    spring版本:4.3.13 ActiveMq版本:5.15 ======================================================== spring整合act ...

  2. (未解决)flume监控目录,抓取文件内容推送给kafka,报错

    flume监控目录,抓取文件内容推送给kafka,报错: /export/datas/destFile/220104_YT1013_8c5f13f33c299316c6720cc51f94f7a0_2 ...

  3. 【原创】大叔问题定位分享(5)Kafka客户端报错SocketException: Too many open files 打开的文件过多

    kafka0.8.1 一 问题 10月22号应用系统忽然报错: [2014/12/22 11:52:32.738]java.net.SocketException: 打开的文件过多 [2014/12/ ...

  4. 【原创】大叔问题定位分享(13)HBase Region频繁下线

    问题现象:hive执行sql报错 select count(*) from test_hive_table; 报错 Error: java.io.IOException: org.apache.had ...

  5. 【原创】大叔问题定位分享(3)Kafka集群broker进程逐个报错退出

    kafka0.8.1 一 问题现象 生产环境kafka服务器134.135.136分别在10月11号.10月13号挂掉: 134日志 [2014-10-13 16:45:41,902] FATAL [ ...

  6. 【原创】大叔问题定位分享(32)mysql故障恢复

    mysql启动失败,一直crash,报错如下: 2019-03-14T11:15:12.937923Z 0 [Note] InnoDB: Uncompressed page, stored check ...

  7. 【原创】大叔问题定位分享(30)mesos agent启动失败:Failed to perform recovery: Incompatible agent info detected

    mesos agent启动失败,报错如下: Feb 15 22:03:18 server1.bj mesos-slave[1190]: E0215 22:03:18.622994 1192 slave ...

  8. 【原创】大叔问题定位分享(28)openssh升级到7.4之后ssh跳转异常

    服务器集群之间忽然ssh跳转不通 # ssh 192.168.0.1The authenticity of host '192.168.0.1 (192.168.0.1)' can't be esta ...

  9. 【原创】大叔问题定位分享(25)ambari metrics collector内置standalone hbase启动失败

    ambari metrics collector内置hbase目录位于 /usr/lib/ams-hbase 配置位于 /etc/ams-hbase/conf 通过ruby启动 /usr/lib/am ...

随机推荐

  1. SpringCloud(7)服务链路追踪Spring Cloud Sleuth

    1.简介 Spring Cloud Sleuth 主要功能就是在分布式系统中提供追踪解决方案,并且兼容支持了 zipkin,你只需要在pom文件中引入相应的依赖即可.本文主要讲述服务追踪组件zipki ...

  2. 最简单易懂的Spring Security 身份认证流程讲解

    最简单易懂的Spring Security 身份认证流程讲解 导言 相信大伙对Spring Security这个框架又爱又恨,爱它的强大,恨它的繁琐,其实这是一个误区,Spring Security确 ...

  3. react的jsx语法

    在webpack.config.js中配置解析的loader { test:/\.jsx?$/, use:{ loader:"babel-loader", options:{ pr ...

  4. webservice异常

    webservice的一个常见异常: [SOAPException: faultCode=SOAP-ENV:Client; msg=Error parsing HTTP status line &qu ...

  5. JQuery的Ajax技术

    jquery是一个优秀的js框架,自然对js原生的ajax进行了封装, 封装后的ajax的操作方法更简洁,功能更强大,与ajax操作 相关的jquery方法有如下几种: Ajax 请求 $.ajax( ...

  6. 爬虫系列之mongodb

    mongo简介 MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非 ...

  7. python发送smtp 邮件 图片

    #-*- coding: utf-8 -*- # python2 import os import time import random import smtplib from time import ...

  8. 【XSY3141】哲学家 计算几何 线段树

    题目描述 有一个平面,最开始平面上没有任何点. 你要按顺序加入 \(n\) 个点,求加入每个点后有多少三角形严格包含原点(在边界上不算). \(n\leq 400000\),无重点. 题解 其实这题本 ...

  9. rest framework 解析器,渲染器

    解析器 解析器的作用 解析器的作用就是服务端接收客户端传过来的数据,把数据解析成自己可以处理的数据.本质就是对请求体中的数据进行解析. 请求体相关字段: Accept:指定了接收的数据类型 Conte ...

  10. dajngo cache,throttling

    缓存 背景介绍: 动态网站的问题就在于它是动态的. 也就是说每次用户访问一个页面,服务器要执行数据库查询,启动模板,执行业务逻辑以及最终生成一个你所看到的网页,这一切都是动态即时生成的. 从处理器资源 ...