ES启动失败:__es__.tmp已经存在

问题

在ES 2.x版本中发生的一起动失败报错:

java.nio.file.FileAlreadyExistsException: /elasticsearch-20/cluster_name/nodes/0/__es__.tmp

问题分析

在ES的源码中通过关键字__es__.tmp找到了相关源码,如下所示:

/**
     * This method tries to write an empty file and moves it using an atomic move operation.
     * This method throws an {@link IllegalStateException} if this operation is
     * not supported by the filesystem. This test is executed on each of the data directories.
     * This method cleans up all files even in the case of an error.
     */
    public void ensureAtomicMoveSupported() throws IOException {
        final NodePath[] nodePaths = nodePaths();
        for (NodePath nodePath : nodePaths) {
            assert Files.isDirectory(nodePath.path) : nodePath.path + " is not a directory";
            final Path src = nodePath.path.resolve("__es__.tmp");
            Files.createFile(src);
            final Path target = nodePath.path.resolve("__es__.final");
            try {
                Files.move(src, target, StandardCopyOption.ATOMIC_MOVE);
            } catch (AtomicMoveNotSupportedException ex) {
                throw new IllegalStateException("atomic_move is not supported by the filesystem on path ["
                        + nodePath.path
                        + "] atomic_move is required for elasticsearch to work correctly.", ex);
            } finally {
                Files.deleteIfExists(src);
                Files.deleteIfExists(target);
            }
        }
    }

ensureAtomicMoveSupported方法是在ES启动时初始化GatewayMetaState对象时调用的,从方法注释可以看出这个方法是为了测试ES运行环境中是否支原子性地移动一个文件。测试的方法就是,先创建一个名为__es__.tmp的文件,在将其移动到名为__es__.final的文件,如果这个操作成功,说明支持,如果报异常说明不支持。测试结束后会通过调用Files.deleteIfExists(src);Files.deleteIfExists(target);将__es__.tmp 与__es__.final这两个文件都删除。
我们再回到ES的报错:

java.nio.file.FileAlreadyExistsException: /elasticsearch-20/cluster_name/nodes/0/__es__.tmp

显然报这个错是因为ensureAtomicMoveSupported方法方法试图创建__es__.tmp的时候他已经存在了。至于为什么存在这个文件,我的推测是,上次ES启动过程中在__es__.tmp创建到删除这段时间,ES进程被强制杀死导致__es__.tmp没有被删除。

所以ES代码没有考虑到这种情况,我认为确实是ES的锅。

解决方法

解决这个异常的方法很容易想到,那就是手动把__es__.tmp删除,再重启ES即可。

另外,需要说明的是ES的开发者已经意识到这个缺陷,并且将其在5.x版本中修复。
他们的修复也非常简单,就是把上述源码中的Files.createFile(src); 移动到try 代码块中即可,这样异常就能被捕获,不会影响ES的启动。

public void ensureAtomicMoveSupported() throws IOException {
        final NodePath[] nodePaths = nodePaths();
        for (NodePath nodePath : nodePaths) {
            assert Files.isDirectory(nodePath.path) : nodePath.path + " is not a directory";
            final Path src = nodePath.path.resolve("__es__.tmp");
            // Files.createFile(src);
            final Path target = nodePath.path.resolve("__es__.final");
            try {
                Files.createFile(src);
                Files.move(src, target, StandardCopyOption.ATOMIC_MOVE);
            } catch (AtomicMoveNotSupportedException ex) {
                throw new IllegalStateException("atomic_move is not supported by the filesystem on path ["
                        + nodePath.path
                        + "] atomic_move is required for elasticsearch to work correctly.", ex);
            } finally {
                Files.deleteIfExists(src);
                Files.deleteIfExists(target);
            }
        }
    }

参考资料

https://github.com/elastic/elasticsearch/issues/19036

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值