hdfs的append 阻止重复追加追加问题

转:/db/nosql/382.shtml
1. HDFS的文件append功能
早期版本的HDFS不支持任何的文件更新操作,一旦一个文件创建、写完数据、并关闭之后,这个文件就再也不能被改变了。为什么这么设计?是为了与MapReduce完美配合,MapReduce的工作模式是接受一系列输入文件,经过map和reduce处理,直接产生一系列输出文件,而不是在原来的输入文件上做原位更新。为什么这么做?因为直接输出新文件比原位更新一个旧文件高效的多。
&&&&&& 在HDFS上,一个文件一直到它的close方法成功执行之后才会存在,才能被其他的client端所看见。如果某个client端在写文件时或者在close文件时失败了,那么这个文件就不会存在,就好像这个文件从来没写过,唯一恢复这个文件的方法,就是从头到尾重新再写一遍。
&&&&&& Hadoop1.x版本一直都不支持文件的append功能,一直到Hadoop 2.x版本,append 功能才被添加到Hadoop Core中,允许向HDFS文件中追加写数据。为此,HDFS Core 也作出了一些重大的改变,以支持这一操作。append功能添加到HDFS经历了一番曲折和一段很长的时间(具体可以参考/blog/2009/07/file-appends-in-hdfs/和 https://issues.apache.org/jira/browse/HADOOP-8230)。
2. HBase 如何完成数据更新和删除操作
&&&&&& HBase依赖于HDFS来存储数据。HBase作为数据库,必须提供对HBase表中数据的增删改查,而HDFS的文件只支持append操作、不支持删除和更新操作,那么HBase如何依赖HDFS完成更新以及删除操作呢??。
2.1 更新操作
&&&&&& HBase表中的数据当存放到HDFS中时,在HDFS看来,已经可以简单的理解成key-value对,其中key可以理解成是由:rowkey+column family+column qualifier+timestamp+type 组成。HBase 对新增的数据以及要更新的数据(理解成key-value对),都直接先写入MemStore结构中,MemStore是完全的内存结构,且是key有序的。当MemStore达到一定大小后,该MemStore一次性从内存flush到HDFS中(磁盘中),生成一个HFile文件,HFile文件同样是key有序的,并且是持久化的位于HDFS系统中的。通过这种机制,HBase对表的所有的插入和更新都转换成对HDFS的HFile文件的创建。
&&&&&& 你可能会迅速的想到,那查询怎么办?
&&&&&& 是的,这种方式解决了插入和更新的问题,而查询就变得相对麻烦。而这也正是HBase设计之初的想法:以查询性能的下降来换取更新性能的提升。
&&&&&& 事实上查询是如下来完成的。
&&&&&& 每当MemStore结构flush到HDFS上时,就会产生一个新的HFile文件,随着时间的推移,会产生一连串的HFile文件,这些HFile文件产生的先后顺序非常的重要,可以想象成他们按创建时间排成一个队列,最近产生的在最前面,较早产生的在最后面。当HBase执行查询操作时(可以理解为给出key,要找到value),首先查询内存中的MemStroe结构,如果命中,就返回结果,因为MemStore中的数据永远是最新的,如果不命中,就从前到后遍历之前产生的HFile文件队列,在每个HFile文件中查找key,看是否命中,如果命中即可返回(最新的数据排在最前面),如果不命中一直查找下去,直到所有HFile文件被搜索完结束。
由此可见,查询操作最坏情况下可能要遍历所有HFile文件,最好情况下在内存中MemStore即可命中,这也是为什么HBase查询性能波动大的原因。当然HBase也不会真的很傻的去遍历每个HFile文件中的内容,这个性能是无法忍受的,它采取了一些优化的措施:1、引入bloomfilter,对HFile中的key进行hash,当查询时,对查询key先过bloomfilter,看查询key是否可能在该HFile中,如果可能在,则进入第2步,不在则直接跳过该HFile;2、还记得吗?HFile是key有序的(具体实现是类SSTable结构),在有序的key上查找就有各种优化技术了,而不是单纯的遍历了。
通过以上机制,HBase很好的解决了插入和更新、以及查找的问题,但是问题还没有结束。细心的朋友很可能已经看出来,上述过程中,HFile文件一直在产生,HFile文件组成的列表一直在增大,而计算机资源是有限的,并且查询的性能也依赖HFile队列的长度,因此我们还需要一种合并HFile文件的机制,以保持适度的HFile文件个数。HBase中实现这种机制采用的是LSM树(一种NOSQL系统广泛使用的结构),LSM能够将多个内部key有序的小HFile文件合并生成一个大的HFile文件,当新的大的HFile文件生成后,HBase就能够删除原有的一系列旧的小的HFile文件,从而保持HFile队列不至于过长,查询操作也不至于查询过多的HFile文件。在LSM合并HFile的时候,HBase还会做很重要的两件事:1、将更新过的数据的旧版本的数据删除掉,只留下最新的版本;2、将标有删除标记(下面一节会讲到)的数据删除掉。
2.2 删除操作
&&&&&& 有了以上机制,HBase完成删除操作非常的简单,对将要删除的key-value对进行打标,通常是对key进行打标,将key中的type字段打标成“删除”标记,并将打标后的数据append到MemStore中,MemStore再flush到HFile中,HFile合并时,检查这个标记,所有带有“删除”标记的记录将被删除而不会合并到新的HFile中,这样HBase就完成了数据的删除操作。
3. HBase 的WAL
HBase的WAL(Write-Ahead-Log)机制是必须的,一个RegionServer通常与一个HLog一一对应,数据写入Region之前先写HLog能够保障数据的安全。 HLog使用Hadoop的SequenceFile存储日志,而HLog是一直连续不断追加写文件的,它强烈依赖SequenceFile的append功能。事实上正是HLog对append功能的强烈需求,或多或少推动了HDFS在最近的版本中添加了文件追加功能。
阅读(...) 评论()往hdfs上追加数据【hadoop写数据】-HDFS-about云开发-第2页
后使用快捷导航没有帐号?
只需一步,快速开始
扫一扫,访问微社区
往hdfs上追加数据【hadoop写数据】
主题帖子积分
中级会员, 积分 364, 距离下一级还需 636 积分
中级会员, 积分 364, 距离下一级还需 636 积分
如果真如楼主所说,那么有两个问题
1.为何楼主的的错误会出现,创建文件失败,创建文件失败,但是却能追 ...
这个真的是能追加成功,但是为什么报错我现在也搞不明白,你说的这个环境配置具体指哪??我在工程里只加了一个hdfs-site.xml,而且没有修改任何配置
主题帖子积分
高级会员, 积分 2017, 距离下一级还需 2983 积分
高级会员, 积分 2017, 距离下一级还需 2983 积分
这个真的是能追加成功,但是为什么报错我现在也搞不明白,你说的这个环境配置具体指哪??我在工程里只加 ...你这个帖子收藏了,有时间验证下。等得出结果,在讨论。也建议楼主可以从多方面验证,可能是环境问题。
欢迎加入about云群 、 ,云计算爱好者群,关注
主题帖子积分
中级会员, 积分 364, 距离下一级还需 636 积分
中级会员, 积分 364, 距离下一级还需 636 积分
你这个帖子收藏了,有时间验证下。等得出结果,在讨论。也建议楼主可以从多方面验证,可能是环境问题。
嗯,我现在在看源码这一块,看到底怎么回事
主题帖子积分
新手上路, 积分 29, 距离下一级还需 21 积分
新手上路, 积分 29, 距离下一级还需 21 积分
咨询个HDFS问题:
&&1. 在多线程高速并发反复append写入文件时存在这个现象;(设计了读写锁对同一文件写入时保护)
&&2. 文件是打开,写入,append,关闭流程;
&&看资料好像是hdfs一种保护机制,具体细节没有研究
数据DataNode节点对应的错误是
14:32:21,700 ERROR [IPC Server handler 14 on 9000] security.UserGroupInformation (UserGroupInformation.java:doAs(1494)) - PriviledgedActionException as:root (auth:SIMPLE) cause:org.apache.hadoop.hdfs.protocol.AlreadyBeingCreatedException: failed to create file /user/root/rcfclient_0723data_thread_00019.txt for DFSClient_NONMAPREDUCE_ on client 10.10.10.253 because current leaseholder is trying to recreate file.
C++接入客户端对应的错误信息如下
hdfsOpenFile(rcfclient_0723data_thread_00019.txt): FileSystem#append((Lorg/apache/hadoop/fs/P)Lorg/apache/hadoop/fs/FSDataOutputS) error:
org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.hdfs.protocol.AlreadyBeingCreatedException): failed to create file /user/root/rcfclient_0723data_thread_00019.txt for DFSClient_NONMAPREDUCE_ on client 10.10.10.253 because current leaseholder is trying to recreate file.
& && &&&at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.recoverLeaseInternal(FSNamesystem.java:2275)
& && &&&at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.appendFileInternal(FSNamesystem.java:2153)
& && &&&at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.appendFileInt(FSNamesystem.java:2386)
& && &&&at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.appendFile(FSNamesystem.java:2347)
& && &&&at org.apache.hadoop.hdfs.server.namenode.NameNodeRpcServer.append(NameNodeRpcServer.java:508)
& && &&&at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolServerSideTranslatorPB.append(ClientNamenodeProtocolServerSideTranslatorPB.java:320)
& && &&&at org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos$ClientNamenodeProtocol$2.callBlockingMethod(ClientNamenodeProtocolProtos.java:59572)
& && &&&at org.apache.hadoop.ipc.ProtobufRpcEngine$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine.java:585)
& && &&&at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:928)
& && &&&at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2048)
& && &&&at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2044)
& && &&&at java.security.AccessController.doPrivileged(Native Method)
& && &&&at javax.security.auth.Subject.doAs(Subject.java:415)
& && &&&at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1491)
& && &&&at org.apache.hadoop.ipc.Server$Handler.run(Server.java:2042)
主题帖子积分
新手上路, 积分 29, 距离下一级还需 21 积分
新手上路, 积分 29, 距离下一级还需 21 积分
同问,解决过或知道问题原因的请站内短信给我
主题帖子积分
高级会员, 积分 1341, 距离下一级还需 3659 积分
高级会员, 积分 1341, 距离下一级还需 3659 积分
顶顶顶!!!!!!
主题帖子积分
新手上路, 积分 14, 距离下一级还需 36 积分
新手上路, 积分 14, 距离下一级还需 36 积分
System. setProperty( &hadoop.home.dir&, &D:/hadoop& );
conf.setBoolean( &dfs.support.append&, true );
& && && & conf.set( &dfs.client.block.write.replace-datanode-on-failure.policy& ,
& && && && && && &&&&NEVER& );
& && && & conf.set( &dfs.client.block.write.replace-datanode-on-failure.enable& ,
& && && && && && &&&&true& );
主题帖子积分
高级会员, 积分 1180, 距离下一级还需 3820 积分
高级会员, 积分 1180, 距离下一级还需 3820 积分
首先修改面配置文件,相信你已经修改了
这个代码对文件追加过一次,再次追加就会报错,不知到如何解决,hadoop 2.5.2&&CDH 5.5.1版都试过了,还没有找到解决方法呢。
主题帖子积分
高级会员, 积分 1180, 距离下一级还需 3820 积分
高级会员, 积分 1180, 距离下一级还需 3820 积分
楼主最后这个问题解决了没?
主题帖子积分
新手上路, 积分 9, 距离下一级还需 41 积分
新手上路, 积分 9, 距离下一级还需 41 积分
public static void appen(String content, String path, FileSystem fs) {
& & & & & & & & // System.out.println(&测试:&+content);
& & & & & & & & InputStream in =
& & & & & & & & OutputStream out =
& & & & & & & & try {
& & & & & & & & & & & & Path hdfs_path = new Path(path);
& & & & & & & & & & & & Configuration conf = new Configuration();
& & & & & & & & & & & & conf.setBoolean(&dfs.support.append&, true);
& & & & & & & & & & & & // FileSystem fs = FileSystem.get(URI.create(hdfs_path.toString()),
& & & & & & & & & & & & // conf);
& & & & & & & & & & & & fs.setReplication(hdfs_path, (short) 1);
& & & & & & & & & & & & in = new BufferedInputStream(new ByteArrayInputStream(
& & & & & & & & & & & & & & & & & & & & content.getBytes()));
& & & & & & & & & & & & out = fs.append(hdfs_path);
& & & & & & & & & & & & IOUtils.copyBytes(in, out, conf);
& & & & & & & & & & & & // fs.close();
& & & & & & & & } catch (Exception e) {
& & & & & & & & & & & & logger.error(e);
& & & & & & & & } finally {
& & & & & & & & & & & & IOUtils.closeStream(in);
& & & & & & & & & & & & try {
& & & & & & & & & & & & & & & & if (in != null) {
& & & & & & & & & & & & & & & & & & & & in.close();
& & & & & & & & & & & & & & & & }
& & & & & & & & & & & & & & & & if (out != null) {
& & & & & & & & & & & & & & & & & & & & out.close();
& & & & & & & & & & & & & & & & }
& & & & & & & & & & & & } catch (IOException e) {
& & & & & & & & & & & & & & & & // TODO Auto-generated catch block
& & & & & & & & & & & & & & & & e.printStackTrace();
& & & & & & & & & & & & }
& & & & & & & & }
我也这问题&&,定时任务一直跑,第一个任务跑完没有问题,任务第二次跑就出像楼主一样的bug.
如果任务一直跑好好的,我把任务手动停了,再跑也会有这bug.&&出现bug后,要过比较久或重启hadoop,就没有这问题。我怀疑文件没有正常关闭,但其实都有关闭
积极上进,爱好学习
经常参与各类话题的讨论,发帖内容较有主见
经常帮助其他会员答疑
站长推荐 /4
云计算hadoop视频大全(新增 yarn、flume|storm、hadoop一套视频
等待验证会员请验证邮箱
新手获取积分方法
技术类问答,解决学习openstack,hadoop生态系统中遇到的问题
Powered by【HDFS】想请教下HDFS的文件可以被多次打开吗? - Hadoop - ITeye群组
请教一个问题,现在有一个需求,期望每天往HDFS中的同一个文件写入数据。
问题是:
HDFS中的文件支持close后再次打开,然后接着在其后边增加内容吗?
hadoop的版本是Hadoop 1.0.3,不支持append操作
另外问下:
append和sync的作用是不是都是在文件未关闭的情况下将文件内容刷新至HDFS中,使得其他访问者可见?
对于要在一个文件结尾进行追加的需求是不是没有现成的API可以实现?
1.0虽然是从0.20.5拉出来的,但已经merge了0.20-append,支持append,append主要是为了hbase要求的强一致性。文件当然可以被多次打开。可以用cdh发行版,避免hadoop的代码branch太多,搞不清用哪个。
相关资源推荐hdfs append追加文件上传的问题 - ITeye问答
各位大神们,小弟设置了hadoop-0.20-cdh3u0版本的dfs.support.append为true,然后想测试下文件追加上传。第一次上传一个文件的前4096看,第二次上传其余部分。但是发现2次上传的文件大小之和小于总文件大小。我发现问题在于,当第二次上传时,hdfs会删除第一次的文件,然后重新建立新文件再上传,所以文件大小只有第二次上传的数据大小。
以下是hadoop的日志:
15:00:04,363 INFO org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit: ugi=dell ip=/172.18.9.55 cmd=create src=/user/tmp/test.jpg dst=null perm=dell:supergroup:rw-r--r--
15:00:04,373 INFO org.apache.hadoop.hdfs.StateChange: BLOCK* NameSystem.allocateBlock: /user/tmp/test.jpg. blk_7
15:00:04,401 INFO org.apache.hadoop.hdfs.StateChange: BLOCK* NameSystem.addStoredBlock: blockMap updated: 172.17.0.122:50010 is added to blk_7 size 4096
15:00:04,403 INFO org.apache.hadoop.hdfs.StateChange: BLOCK* NameSystem.addStoredBlock: blockMap updated: 172.17.0.123:50010 is added to blk_7 size 4096
15:00:04,406 INFO org.apache.hadoop.hdfs.StateChange: BLOCK* NameSystem.addStoredBlock: blockMap updated: 172.17.0.121:50010 is added to blk_7 size 4096
15:00:04,409 INFO org.apache.hadoop.hdfs.StateChange: Removing lease on& file /user/tmp/test.jpg from client DFSClient_
15:00:04,409 INFO org.apache.hadoop.hdfs.StateChange: DIR* pleteFile: file /user/tmp/test.jpg is closed by DFSClient_
15:00:06,429 INFO org.apache.hadoop.hdfs.StateChange: BLOCK* NameSystem.addToInvalidates: blk_6612403 is added to invalidSet of 172.17.0.122:50010
15:00:06,429 INFO org.apache.hadoop.hdfs.StateChange: BLOCK* NameSystem.addToInvalidates: blk_6612403 is added to invalidSet of 172.17.0.123:50010
15:00:06,429 INFO org.apache.hadoop.hdfs.StateChange: BLOCK* NameSystem.addToInvalidates: blk_6612403 is added to invalidSet of 172.17.0.121:50010
15:00:06,430 INFO org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit: ugi=dell ip=/172.18.9.55 cmd=delete src=/user/tmp/test.jpg dst=null perm=null
15:00:06,431 INFO org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit: ugi=dell ip=/172.18.9.55 cmd=create src=/user/tmp/test.jpg dst=null perm=dell:supergroup:rw-r--r--
15:00:06,435 INFO org.apache.hadoop.hdfs.StateChange: BLOCK* NameSystem.allocateBlock: /user/tmp/test.jpg. blk_8
15:00:06,464 INFO org.apache.hadoop.hdfs.StateChange: BLOCK* NameSystem.addStoredBlock: blockMap updated: 172.17.0.120:50010 is added to blk_8 size 39455
15:00:06,465 INFO org.apache.hadoop.hdfs.StateChange: BLOCK* NameSystem.addStoredBlock: blockMap updated: 172.17.0.122:50010 is added to blk_8 size 39455
15:00:06,467 INFO org.apache.hadoop.hdfs.StateChange: BLOCK* NameSystem.addStoredBlock: blockMap updated: 172.17.0.121:50010 is added to blk_8 size 39455
15:00:06,469 INFO org.apache.hadoop.hdfs.StateChange: Removing lease on& file /user/tmp/test.jpg from client DFSClient_
最终文件大小为:39455
求各位大神给小弟解决办法。
采纳的答案
换个版本试试呢,如果你配置hdfs-site.xml
&&&& &property&
&&&&&&& &name&dfs.support.append&/name&
&&&&&&& &value&true&/value&
&&&& &/property&
通过append方法就可以实现文件追加的
已解决问题
未解决问题用户名:qianqian_520
文章数:31
评论数:11
访问量:80096
注册日期:
阅读量:1297
阅读量:3317
阅读量:458454
阅读量:1143095
51CTO推荐博文
HDFS文件追加hdfs中文件可以追加写,步骤如下:1、配置集群(hdfs-site.xml),必须配置才可以&&&property&&&&&&&&&&name&dfs.support.append&/name&&&&&&&&&&value&true&/value&&&&&/property&&2、API实现String hdfs_path= "hdfs://ip:xx/file/fileuploadFileName";//文件路径
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create(hdfs_path), conf);
InputStream in = new BufferedInputStream(new FileInputStream(file));//要追加的文件流,file为文件
OutputStream out = fs.append(new Path(hdfs_path));
IOUtils.copyBytes(in, out, 4096, true);&&&本文出自 “” 博客,转载请与作者联系!
了这篇文章
类别:┆阅读(0)┆评论(0)

我要回帖

更多关于 hdfs 文件 append 的文章

 

随机推荐