最近在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. 在物理内存中观察CLR托管内存及GC行为

    虽然看了一些书,还网络上的一些博文,不过对CLR托管内存细节依然比较模糊.而且因为工作原因总会有很多质疑,想要亲眼看到内存里二进制数据的变化. 所以借助winhex直接查看内存以证实书上的描述或更进一 ...

  2. CGPoint、CGSize、CGRect、CGRectEdge的详细使用

    http://blog.sina.com.cn/s/blog_953e22700101r7lz.html 在CGGeometry.h里的 CGPoint.CGSize.CGRect.CGRectEdg ...

  3. JEECG 3.8宅男优化版本发布

    1024程序员节宅男节日快乐 -- JAVA快速开发平台,JEECG 3.8宅男优化版本发布 - JEECG开源社区 - CSDN博客https://blog.csdn.net/zhangdaisco ...

  4. Yesterday when I was young

    Somehow, it seems the love I knew was always the most destructive kind 不知为何,我经历的爱情总是最具毁灭性的的那种 Yester ...

  5. SpringCloud入门(一)

    一.微服务概述 1.什么是微服务 目前的微服务并没有一个统一的标准,一般是以业务来划分将传统的一站式应用,拆分成一个个的服务,彻底去耦合,一个微服务就是单功能业务,只做一件事. 与微服务相对的叫巨石 ...

  6. yum 安装fuser命令

    yum install -y psmisc 转自:https://www.cnblogs.com/saneri/p/5465718.html 有时候我们需要umount某个挂载目录时会遇到如下问题: ...

  7. jdk安装及配置

    点击jdk文件运行 安装完成后的目录: 2,在系统变量下面配置 JAVA_HOME:你自己的jdk的路径 CLASSPATH= .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME% ...

  8. LODOP超文本简短问答和相关内容

    html样式查看lodop内部解析的html信息,见http://www.c-lodop.com/faq/pp8.html分析差异点,因浏览器版本不同遵循的html标准不同,造成某些标签属性显示有差异 ...

  9. Lodop打印表格带页头页尾 高度是否包含页头页尾

    通过设置TableHeightScope,可以实现对ADD_PRINT_TABLE,表格带页头页尾,查看本博客另一篇博文:Lodop打印表格带页头页尾 自动分页每页显示头尾 超文本超过打印项高度,会自 ...

  10. C. New Year and Rating 差分方程 思维

    题意: 一个CF玩家打CF 给出其比赛列表和上分(掉分)情况 ,但是没给初始分 问最后最高分是多少  (情况不存在,或者可能无穷大) 思路: 设初始分为x 那么之前的回合的分数前缀和为sum    如 ...