python 与hadoop之pyhdfs的append

时间:2021-03-30 19:53:07

由于项目需要,所以就涉及到append功能;

HDFS设计之处并不支持给文件追加内容,这样的设计是有其背景的(如果想了解更多关于HDFS的append的曲折实现,可以参考《File Appends in HDFS》:
http://blog.cloudera.com/blog/2009/07/file-appends-in-hdfs/),但从HDFS2.x开始支持给文件追加内容,可以参见
https://issues.apache.org/jira/browse/HADOOP-8230
可以再看看
http://www.quora.com/HDFS/Is-HDFS-an-append-only-file-system-Then-how-do-people-modify-the-files-stored-on-HDFS
正如HADOOP-8230所述,只需要将hdfs-site.xml中的以下属性修改为true就行。
hadoop2.4.0:

<property>
<name>dfs.support.append</name>
<value>true</value>
</property>

hadoop1.2.1:

<property>
<name>dfs.support.broken.append</name>
<value>true</value>
</property>

这样修改过后,hadoop就支持追加模式了,但是由于追加模式中还有一定的问题,所以apache不建议在追求稳定的项目中使用(它也主要来时支持hbase的);
但是问题又来了,当你都设置好了,但是在打开文件为“a”模式时会报错:
“File append is not supported yet”;

然后我就去看看了libhdfs的源码(src文件中的pyhdfs.c)。
再打开文件模块,原来是这样写的:

if (!strcmp(mode, "r")) {
flags = O_RDONLY;
} else if (!strcmp(mode, "w")) {
flags = O_WRONLY;
} else if (!strcmp(mode, "a")) {
**/* append is disabled by default
flags = O_WRONLY | O_APPEND; */

PyErr_SetString(PyExc_ValueError, "File append is not supported yet");
return NULL;**
} else {
/* bad open mode */
PyErr_SetString(PyExc_ValueError, "Unknown file open mode");
return NULL;
}

所以得知,libhdfs默认是不支持append模式的;但是可是改一下就好了:

if (!strcmp(mode, "r")) {
flags = O_RDONLY;
} else if (!strcmp(mode, "w")) {
flags = O_WRONLY;
} else if (!strcmp(mode, "a")) {
/* append is abled */
flags = O_WRONLY | O_APPEND;
} else {
/* bad open mode */
PyErr_SetString(PyExc_ValueError, "Unknown file open mode");
return NULL;
}

改过后重新安装一次libhdfs库就可以使用了(也只是最初的想法);
然而在真正写的过程中又报错了:
错误:
java.io.IOException: Failed to replace a bad datanode on the existing pipeline due to no more good datanodes being available to try.*
解决的方法是:
修改hdfs-site.xml文件,添加或者修改如下两项:

<property>
<name>dfs.client.block.write.replace-datanode-on-failure.enable</name>
<value>true</value>
</property>
<property>
<name>dfs.client.block.write.replace-datanode-on-failure.policy</name>
<value>NEVER</value>
</property>

解释如下:
对于dfs.client.block.write.replace-datanode-on-failure.enable,客户端在写失败的时候,是否使用更换策略,默认是true没有问题。
对于,dfs.client.block.write.replace-datanode-on-failure.policy,default在3个或以上备份的时候,是会尝试更换结点尝试写入datanode。而在两个备份的时候,不更换datanode,直接开始写。对于3个datanode的集群,只要一个节点没响应写入就会出问题,所以可以关掉。(内容来至http://www.sharpcloud.cn/thread-4927-1-1.html博主记录了他遇到的所有错误,很有用)
这样弄过后,就可以成功的写入了;