You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 删除过期锁记录:

  1. 进入 Cassandra 容器:docker exec -it <cassandra-container-id> cqlsh
  2. 切换到 JanusGraph 对应 keyspace(默认 janusgraph):USE janusgraph;
  3. 查询锁表记录:SELECT * FROM system_lock;
  4. 删除目标过期锁: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 22:15:23