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看,拋出的異常應該是鎖出現了問題,文件損壞或者目錄損壞、或者文件系統損壞導致。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM