Java中使用renameTo方法导致文件数据缺失

开发的时候发现了es里面数据有缺失,排查了好久,最后怀疑是renameTo方法的时候,在renameTo还没有完成的时候,程序就对生成的文件进行了处理,实际上这个时候文件还没有完全进入目标文件夹

这完全是一个偶发的问题,但是,发生的频率并不算太低,基本上每小时12个点的文件,总会有一个点出现这种情况,我并没有做完全的统计,因为总体数据量比较大。

于是我在renameTo操作后加了一个线程等待一秒钟的操作,就是为了防止出现这种文件还未转移完全的情况

并且我打印了两行日志,看一下被renameTo前后文件是不是有差异

结果果然是,renameTo前后的数据竟然相差相当大

在这里插入图片描述

我研究了一下renameTo的源码,发现最后是调用的native方法

private native boolean rename0(File f1, File f2);

我猜测是rename0方法是在开始执行的时候,发现文件可以移动就返回了true,而此时其实刚开始执行数据移动操作,数据移动还没有完成,理论上这种移动会很快。程序进行操作的文件,13000行的数据,也没有产生问题,为什么2000行的数据会缺失。是不是如果遇到了机器IO极大的时候,可能会影响数据的转移。在转移了部分数据之后,我的程序开始了读操作,然后就出现了不可写入的情况。剩下的数据也就不会再写入了。

但是伴随而来的就是一个问题,rename0方法到底是以什么形式进行转移文件的,未完全转移的时候是否允许对文件进行读写操作。如果允许,那么我猜测可能成立,如果不允许,我的猜测就不成立了。

我开始想调大一点sleep时间,但是每一秒对于上万个文件的处理速度都是很大的影响。我现在发现,我甚至没办法判断rename0是否完成了。

最后处理办法决定通过复制再删除的方法完成试一下,原来的renameTo换成了jdk提供的一个FileChannel的方式实现

                try {
                    FileUtil.copyFileUsingFileChannels(backFile,backuppath);
                    backFile.delete();
                }catch (Exception e){
                    LOGGER.error("文件复制失败:"+backPath);
                }

copyFileUsingFileChannels方法

    public static void copyFileUsingFileChannels(File source, File dest)
            throws IOException {
        FileChannel inputChannel = null;
        FileChannel outputChannel = null;
        try {
            inputChannel = new FileInputStream(source).getChannel();
            outputChannel = new FileOutputStream(dest).getChannel();
            outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
        } finally {
            inputChannel.close();
            outputChannel.close();
        }
    }

目前观察程序还没有出现缺失数据的情况,待后续观察

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

如我一般的人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值