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看,抛出的异常应该是锁出现了问题,文件损坏或者目录损坏、或者文件系统损坏导致。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」