我们的集群在用fluentd写入hdfs的时候经常会遇到写入失败的问题,失败的特点是写入失败的那个文件的备份数只有2个(我们集群设置的是3个),然后就再也不能成功的往这个文件写入任何内容了。
问题描述
在集群负载比较高的时候,写hdfs文件有时会发生写入错误,写入错误的文件只有两个备份,该文件之后再也不能被写入了。
临时解决
之前还不知道产生这个问题的具体原因,但是出现了文件写入不进去的情况,又要及时的修复问题,我们的做法是先把该文件从hdfs上下载到本地,然后再把该文件从hdfs上删除,最后把本地的文件上传到hdfs中,这样就能把出问题的文件给修复好。
上述的解决方法,毕竟治标不治本,如果出错的文件比较少的话,还可以及时的修复,但是如果错误的文件数很多的话,那修复起来就非常的麻烦了。
彻底解决
产生该问题的原因
之前还不知道具体是什么原因造成的写入失败,后面在研究了hdfs写入过程的时候发现一个问题:那就是我们集群的机器数量比较少,只有四台机器,在写入hdfs文件pipeline的时候,如果有一台机器出现问题了时候,这时候就会把这台机器排除掉,去寻找新的可用的机器,但是我们的集群只有四台机器,如果刚好有两台机器出现问题的话,这时候文件的备份数永远也到达不了3。
解决问题的思路
解决问题的方法无非就下面几个:
- 增加集群的机器数量。比如把集群的机器增加到10台,这样只有同时有8台机器出现问题的情况下,才会出现文件写入失败的问题。这样出现写入失败的问题的概率就会大大的减少。
- 减少文件备份的数量。这个方法对我们不适用,因为我们现在使用的只有3个备份,这个应该是hdfs最低的要求了。
- 修改配置,让写入的行为发生改变。dfs.client.block.write.replace-datanode-on-failure.enable配置默认是true,表示如果在写入的pipeline有datanode失败的时候是否要切换到新的机器,但是如果集群比较小的话,有两台机器失败的话,就没有其他机器可以切换了,所以把该配置设置成false后就能解决问题。
最后的解决方法
由于我们的集群不可能一下子就扩大,所以我们当前的解决方法是先把dfs.client.block.write.replace-datanode-on-failure.enable配置项设置成false,等后面集群变大后再把该配置项改成true。
总结
现在集群已经很久没有发生上述的错误了,说明配置的修改已经起到效果了。解决问题最重要的一步还是找到问题的原因,然后一次性解决掉,不然问题还是会时不时的光顾你的。