ES failed to notify ClusterStateListener java.lang.IllegalStateException: environment is not locked

简介:

ES出现异常:

failed to notify ClusterStateListener
java.lang.IllegalStateException: environment is not locked

定位代码:

 

下载ES 5.5源码,在main/java/org/elasticsearch/env/NodeEnvironment.java 里可以看到:

复制代码
    private void assertEnvIsLocked() {
        if (!closed.get() && locks != null) {
            for (Lock lock : locks) {
                try {
                    lock.ensureValid();
                } catch (IOException e) {
                    logger.warn("lock assertion failed", e);
                    throw new IllegalStateException("environment is not locked", e);
                }
            }
        }
    }
复制代码
assertEnvIsLocked调用地方,可以看到在检测ES node数据路径、index路径使用:
复制代码
    /**
     * Returns an array of all of the nodes data locations.
     * @throws IllegalStateException if the node is not configured to store local locations
     */
    public Path[] nodeDataPaths() {
        assertEnvIsLocked();
        Path[] paths = new Path[nodePaths.length];
        for(int i=0;i<paths.length;i++) {
            paths[i] = nodePaths[i].path;
        }
        return paths;
    }

    /**
     * Returns an array of all of the {@link NodePath}s.
     */
    public NodePath[] nodePaths() {
        assertEnvIsLocked();
        if (nodePaths == null || locks == null) {
            throw new IllegalStateException("node is not configured to store local location");
        }
        return nodePaths;
    }

    public int getNodeLockId() {
        assertEnvIsLocked();
        if (nodePaths == null || locks == null) {
            throw new IllegalStateException("node is not configured to store local location");
        }
        return nodeLockId;
    }

    /**
     * Returns all index paths.
     */
    public Path[] indexPaths(Index index) {
        assertEnvIsLocked();
        Path[] indexPaths = new Path[nodePaths.length];
        for (int i = 0; i < nodePaths.length; i++) {
            indexPaths[i] = nodePaths[i].resolve(index);
        }
        return indexPaths;
    }
复制代码

 

而locks变量的赋值在:
复制代码
 public NodeEnvironment(Settings settings, Environment environment) throws IOException {

        if (!DiscoveryNode.nodeRequiresLocalStorage(settings)) {
            nodePaths = null;
            sharedDataPath = null;
            locks = null;
            nodeLockId = -1;
            nodeMetaData = new NodeMetaData(generateNodeId(settings));
            logger = Loggers.getLogger(getClass(), Node.addNodeNameIfNeeded(settings, this.nodeMetaData.nodeId()));
            return;
        }
        final NodePath[] nodePaths = new NodePath[environment.dataWithClusterFiles().length];
        final Lock[] locks = new Lock[nodePaths.length];
        boolean success = false;
。。。
复制代码

查了下Lock这个类:

import org.apache.lucene.store.Lock

 

作用:

  • org.apache.lucene.store.Lock
  • An interprocess mutex lock.

    Typical use might look like:

     new Lock.With(directory.makeLock("my.lock")) { public Object doBody() { ... code to execute while locked ... } }.run();

    一些加锁、解锁例子 https://www.programcreek.com/java-api-examples/index.php?api=org.apache.lucene.store.Lock
    lucene锁的作用,写保护:在Lucene中,打开一个IndexWrite之后,就会自动在索引目录中生成write.lock文件,这个文件中并不会有内容,不管是在索引打开期间还是在索引关闭之后,其大小都为0KB,并且在IndexWriter关闭之后,并不会删除该文件。如果同时打开多个IndexWriter的话,后打开的IndexWriter就会抛出LockObtainFailedException异常。这是个很重要的保护机制,因为若针对同一索引打开两个writer的话,会导致索引损坏。所以Lucene中的锁主要针对并发写的情况,在写的过程中并不会影响到并发读操作。

    1. lucene并发规则

    a,任意数量的只读属性IndexReader类都可以同时打开一个索引。

    b,对于一个索引来说,一次只能打开一个IndexWriter对象。lucene采用锁来提供保障。

    c,IndexReader可以在indexwriter正在修改索引时打开。该对象只有在IndexWriter提交修改或自己重新打开后才能获知索引的修改情况。

    d,任意多个线程可以共享同一个indexreader或indexwriter。

     

    2. lucene锁机制

    为了实现单一的writer,lucene采用了基于文件的锁,如果锁文件(默认writer.lock)存在于你的索引所在目录内,说明此时正在打开一个writer。此时若企图对同一个索引文件创建其他的writer的话,将产生一个LockObtainFailedException异常。


    而由assertEnvIsLocked看,抛出的异常应该是锁出现了问题,文件损坏或者目录损坏、或者文件系统损坏导致。











本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/bonelee/p/7909194.html,如需转载请自行联系原作者

相关文章
|
2月前
|
安全 Java
Java中WAIT和NOTIFY方法调用时机的深层解析
在Java多线程编程中,`wait()`和`notify()`方法的正确使用对于线程间的协调至关重要。这两个方法必须在同步块或同步方法中调用,这一规定的深层原因是什么呢?本文将深入探讨这一机制。
46 5
|
2月前
|
安全 Java 开发者
Java中WAIT和NOTIFY方法必须在同步块中调用的原因
在Java多线程编程中,`wait()`和`notify()`方法是实现线程间协作的关键。这两个方法必须在同步块或同步方法中调用,这一要求背后有着深刻的原因。本文将深入探讨为什么`wait()`和`notify()`方法必须在同步块中调用,以及这一机制如何确保线程安全和避免死锁。
47 4
|
2月前
|
安全 Java 开发者
深入解读JAVA多线程:wait()、notify()、notifyAll()的奥秘
在Java多线程编程中,`wait()`、`notify()`和`notifyAll()`方法是实现线程间通信和同步的关键机制。这些方法定义在`java.lang.Object`类中,每个Java对象都可以作为线程间通信的媒介。本文将详细解析这三个方法的使用方法和最佳实践,帮助开发者更高效地进行多线程编程。 示例代码展示了如何在同步方法中使用这些方法,确保线程安全和高效的通信。
76 9
|
2月前
|
Java
JAVA多线程通信:为何wait()与notify()如此重要?
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是实现线程间通信的核心机制。它们通过基于锁的方式,使线程在条件不满足时进入休眠状态,并在条件满足时被唤醒,从而确保数据一致性和同步。相比其他通信方式,如忙等待,这些方法更高效灵活。 示例代码展示了如何在生产者-消费者模型中使用这些方法实现线程间的协调和同步。
43 3
|
7月前
|
Java 程序员
从菜鸟到大神:JAVA多线程通信的wait()、notify()、notifyAll()之旅
【6月更文挑战第21天】Java多线程核心在于wait(), notify(), notifyAll(),它们用于线程间通信与同步,确保数据一致性。wait()让线程释放锁并等待,notify()唤醒一个等待线程,notifyAll()唤醒所有线程。这些方法在解决生产者-消费者问题等场景中扮演关键角色,是程序员从新手到专家进阶的必经之路。通过学习和实践,每个程序员都能在多线程编程的挑战中成长。
64 6
|
3月前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
26 1
|
3月前
|
Java
在Java多线程编程中,`wait()`和`notify()`方法的相遇如同一场奇妙的邂逅
在Java多线程编程中,`wait()`和`notify()`方法的相遇如同一场奇妙的邂逅。它们用于线程间通信,使线程能够协作完成任务。通过这些方法,生产者和消费者线程可以高效地管理共享资源,确保程序的有序运行。正确使用这些方法需要遵循同步规则,避免虚假唤醒等问题。示例代码展示了如何在生产者-消费者模型中使用`wait()`和`notify()`。
37 1
|
3月前
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
58 1
|
3月前
|
Java
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是线程间通信的核心机制。
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是线程间通信的核心机制。它们通过基于锁的方式,使线程在条件不满足时进入休眠状态,并在条件成立时被唤醒,从而有效解决数据一致性和同步问题。本文通过对比其他通信机制,展示了 `wait()` 和 `notify()` 的优势,并通过生产者-消费者模型的示例代码,详细说明了其使用方法和重要性。
51 1
|
7月前
|
安全 Java
JAVA多线程通信新解:wait()、notify()、notifyAll()的实用技巧
【6月更文挑战第20天】Java多线程中,`wait()`, `notify()`和`notifyAll()`用于线程通信。在生产者-消费者模型示例中,它们确保线程同步。`synchronized`保证安全,`wait()`在循环内防止虚假唤醒,`notifyAll()`避免唤醒单一线程问题。关键技巧包括:循环内调用`wait()`,优先使用`notifyAll()`以保证可靠性,以及确保线程安全和正确处理`InterruptedException`。
66 0