java - Titan Cassandra 多线程事务锁定

标签 java multithreading cassandra locking titan

我创建了一个包含Graph 的类。例如:

public class GraphManager(){
    Graph graph;
    public GraphManager(Graph graph){
        this.graph = graph;
    }
    public void commitGraph(){
        graph.commit();
    }
}

GraphManager 允许我以预定义的方式与图形进行交互。我使用工厂构造此 GraphManager:

public class GraphManagerFactory(){
    public static GraphManager getGraphManager(){
        return new GraphManager(TitanFactory.open("conf/titan-cassandra.properties"));
    }
}

这是基础框架。现在解决问题,使用休息 Controller 我收到一个 JSON 文件。这导致实例化一个 GraphManager,它将文件转换为图形,然后提交它。基本范式如下:

public class Controller(){
    public List<String> handleRequest(){
        GraphManager manager = GraphManagerFactory.getGraphManager();
        //Do some work with graph manager
        synchronised(Controller.class){
            manager.commitGraph();
        }
    }
}

通过上面的代码,我保证在任何时候只有一个线程可以提交到图表。然而尽管如此,我仍然得到一个PermanentLockingException:

com.thinkaurelius.titan.diskstorage.locking.PermanentLockingException: Local lock contention
at com.thinkaurelius.titan.diskstorage.locking.AbstractLocker.writeLock(AbstractLocker.java:313) ~[titan-core-1.0.0.jar:na]
at com.thinkaurelius.titan.diskstorage.locking.consistentkey.ExpectedValueCheckingStore.acquireLock(ExpectedValueCheckingStore.java:89) ~[titan-core-1.0.0.jar:na]
at com.thinkaurelius.titan.diskstorage.keycolumnvalue.KCVSProxy.acquireLock(KCVSProxy.java:40) ~[titan-core-1.0.0.jar:na]
at com.thinkaurelius.titan.diskstorage.BackendTransaction.acquireIndexLock(BackendTransaction.java:240) ~[titan-core-1.0.0.jar:na]
at com.thinkaurelius.titan.graphdb.database.StandardTitanGraph.prepareCommit(StandardTitanGraph.java:554) ~[titan-core-1.0.0.jar:na]
at com.thinkaurelius.titan.graphdb.database.StandardTitanGraph.commit(StandardTitanGraph.java:683) ~[titan-core-1.0.0.jar:na]
at com.thinkaurelius.titan.graphdb.transaction.StandardTitanTx.commit(StandardTitanTx.java:1352) [titan-core-1.0.0.jar:na]
at com.thinkaurelius.titan.graphdb.tinkerpop.TitanBlueprintsGraph$GraphTransaction.doCommit(TitanBlueprintsGraph.java:263) [titan-core-1.0.0.jar:na]
at org.apache.tinkerpop.gremlin.structure.util.AbstractTransaction.commit(AbstractTransaction.java:94) [gremlin-core-3.0.2-incubating.jar:3.0.2-incubating]
at io.mindmaps.core.accessmanager.GraphAccessManagerImpl.commit(GraphAccessManagerImpl.java:811) [mindmaps-core-0.0.5-SNAPSHOT.jar:na]
at io.mindmaps.graphmanager.listener.TransactionController.commitGraph(TransactionController.java:98) [classes/:na]
at io.mindmaps.graphmanager.listener.TransactionController.validateAndCommit(TransactionController.java:84) [classes/:na]
at io.mindmaps.graphmanager.listener.TransactionController.loadData(TransactionController.java:66) [classes/:na]
at io.mindmaps.graphmanager.listener.TransactionController.lambda$postTransaction$0(TransactionController.java:43) [classes/:na]
at io.mindmaps.graphmanager.loader.QueueManager.handleJob(QueueManager.java:76) ~[classes/:na]
at io.mindmaps.graphmanager.loader.QueueManager.lambda$addJob$3(QueueManager.java:24) ~[classes/:na]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_66]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_66]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_66]
at java.lang.Thread.run(Thread.java:745) ~[na:1.8.0_66]

当一次只允许一次提交时,怎么会发生这种情况?

最佳答案

虽然我接受的答案是 100% 正确的。我想更清楚地强调我为避免锁争用所做的工作(其中大部分是基于/感谢已接受的答案):

第 1 步: 按照建议,我在每个 GraphManager 中包装了一个新事务,而不是包装图形实例。即我按如下方式制作了工厂:

public class GraphManagerFactory(){
    TitanGraph instance;
    public static GraphManager getGraphManager(){
        if(instance = null){
            instance = TitanFactory.open("conf/titan-cassandra.properties");
        }
        return new GraphManager(instance.newTransaction());
    }
}

这一步带来了很多改进。我仍然有锁争用,但它们得到了更快的解决。

第 2 步: 第一次构建图形时,我还提前提供了架构。具体来说,我什至在添加第一个顶点之前就明确地构建了它们,而不是让 titan 隐式构建顶点属性和边。这是使用 management.makeEdgeLabel(label).make(); 边缘标签和 management.makePropertyKey(label).dataType(String.class).make(); 的简单问题。 用于顶点属性。这样做的另一个好处是我可以更轻松地执行批量加载。这意味着再次将 Factory 扩展为:

public class GraphManagerFactory(){
    TitanGraph instance;
    public static GraphManager getGraphManager(){
        if(instance = null){
            instance = TitanFactory.open("conf/titan-cassandra.properties");
            TitanManagement management = instance.openManagement();
            //Check if the labels exist before creating explicitly. 
            //If they don't exist do the following:
            management.makeEdgeLabel("EdgeLabel").make();
            management.makePropertyKey("property").dataType(String.class).make();
            management.commit();
        }
        return new GraphManager(instance.newTransaction());
    }
}

第 3 步: 几乎完全消除争用的最后一步是将 id block 大小增加到 graph.configuration().setProperty("ids.block-size", 100000) ; 。这最后一步可能只适用于我,因为我同时执行大型加载操作。

关于java - Titan Cassandra 多线程事务锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34851775/

相关文章:

python - Cassandra-Django python应用方法

java - 如果磁盘中没有空间,Cassandra 将终止

java - 输入字符串未知时的字符串分割(Java Android 短信分割转发)

javascript - 无法理解 NodeJS 中的一些基本逻辑

c# - 如何正确启动和取消任务。

c# - 如何正确关闭已创建多个线程的 C# 应用程序?

java - 在 Cassandra 中使用 Java(datastax 驱动程序)按时间戳进行选择

java - KafkaSpout 工作示例

java - 像 Windows Phone 7/.NET 中那样的数据绑定(bind)?

java.sql.SQLException : No suitable driver, com.mysql.jdbc.Driver 异常