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

Java中使用renameTo方法导致文件数据缺失,第1张

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();
        }
    }

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/3980033.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-10-21
下一篇 2022-10-21

发表评论

登录后才能评论

评论列表(0条)

保存