JanusGraph频繁抛出TemporaryLockingException的原因及锁释放方法
JanusGraph v1.x.x 连接 Cassandra v3.x.x 时 TemporaryLockingException 问题解决
问题概述
使用 JanusGraph v1.x.x 连接 Docker 部署的 Cassandra v3.x.x 时,频繁触发 TemporaryLockingException,提示特定 KeyColumn 的锁被其他实例持有。日志显示系统已丢弃多条过期锁声明,但仍无法正常获取锁,需解决锁释放、强制获取或重置锁状态的问题。
异常日志
2023-05-11 12:52:47,609 [INFO] [o.j.d.u.BackendOperation.main] :: Temporary exception during backend operation [CacheMutation]. Attempting backoff retry. org.janusgraph.diskstorage.locking.TemporaryLockingException: Lock on KeyColumn [k=0x0xD8000000003FDD80, c=0x0x24] already held by 0x6330613835363363363738302D726D742D6C61702D77696E323031 (we are 0x633061383536336331353636342D726D742D6C61702D77696E323031)
测试代码
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.janusgraph.core.JanusGraph; import org.janusgraph.core.JanusGraphFactory; import org.janusgraph.core.JanusGraphVertex; public class Test9 { private static final Logger logger = LogManager.getLogger(Main.class); public static void main(String[] args) { JanusGraph janusGraph = JanusGraphFactory.build().set("storage.backend", "cql").set("storage.hostname", "localhost:9042").open(); GraphTraversalSource g = janusGraph.traversal(); janusGraph.tx().rollback(); commitAndOpenJanusgraph(janusGraph); logger.info("g.V().count().next():\t" + g.V().count().next()); g.V().limit(1).drop().iterate(); commitAndOpenJanusgraph(janusGraph); logger.info("g.V().count().next():\t" + g.V().count().next()); janusGraph.close(); } private static void commitAndOpenJanusgraph(JanusGraph janusGraph) { janusGraph.tx().commit(); janusGraph.tx().open(); } }
环境信息
- Java 17
- Maven 3
- 存储后端:Cassandra v3.x.x(Docker 容器)
- JanusGraph v1.x.x
解决方案
1. 调整 JanusGraph 锁超时与清理配置
JanusGraph 默认锁参数可能不匹配当前场景,添加以下配置缩短超时时间并增强过期锁清理:
# 锁持有超时时间(毫秒),默认60000,可调整为30000 storage.lock.wait-time=30000 # 过期锁清理间隔(毫秒),默认300000,可调整为60000 storage.lock.clean-interval=60000 # 强制清理过期锁(确保开启,默认true) storage.lock.forced-clean=true
2. 手动清理 Cassandra 中的锁数据
若自动清理失效,直接操作 Cassandra 删除过期锁记录:
- 进入 Cassandra 容器:
docker exec -it <cassandra-container-id> cqlsh - 切换到 JanusGraph 对应 keyspace(默认
janusgraph):USE janusgraph; - 查询锁表记录:
SELECT * FROM system_lock; - 删除目标过期锁:
DELETE FROM system_lock WHERE key = 0x0xD8000000003FDD80 AND column = 0x0x24;
注意:操作前需确认持有该锁的实例已停止,避免数据不一致
3. 优化代码事务处理逻辑
测试代码中频繁提交/开启事务可能导致锁未正确释放,调整如下:
- 避免短时间内重复提交事务,JanusGraph 会在需要时自动开启新事务
- 删除操作后无需手动调用
tx().open(),简化事务流程
修改后的代码示例:
public static void main(String[] args) { try (JanusGraph janusGraph = JanusGraphFactory.build().set("storage.backend", "cql").set("storage.hostname", "localhost:9042").open()) { GraphTraversalSource g = janusGraph.traversal(); janusGraph.tx().rollback(); logger.info("g.V().count().next():\t" + g.V().count().next()); g.V().limit(1).drop().iterate(); janusGraph.tx().commit(); // 提交后无需手动开启事务 logger.info("g.V().count().next():\t" + g.V().count().next()); } }
4. 检查实例 ID 冲突
日志显示两个不同实例 ID 争夺锁,若容器环境主机名重复,手动指定唯一实例 ID:
storage.lock.id=unique-instance-id-001
内容的提问来源于stack exchange,提问作者Zach
相关产品推荐
相关产品推荐

