zoukankan      html  css  js  c++  java
  • JanusGraph中的事务

    翻译整理:纪玉奇
     
    几乎所有与JanusGraph的交互都是通过Transaction,JansuGraph的Transaction支持并发。使用Transaction时,不需要显式进行生命,graph.V()即会开启一个事务,graph.commit()则会提交一个事务。用户也可以使用graph.newTransaction()获取对事务的控制权。
    另外,事务不一定是ACID,而是依赖于后端支持情况,如果是BerkleyDB则可以,但不被Cassandra和HBase支持。

    Transaction Handling

    对JanusGraph的每个操作都是在事务执行,无需显式声明,由第一次操作开启。
    graph = JanusGraphFactory.open("berkeleyje:/tmp/janusgraph")
    juno = graph.addVertex() //Automatically opens a new transaction
    juno.property("name", "juno")
    graph.tx().commit() //Commits transaction
     
    事务在commit()或数据库shutdown()时才结束。

    Transaction Scope

    vertices, edges和type都在transaction scope的范围中,在Tinpop的默认语法,transaction是自动创建的,一旦提交和关闭,元素则不可用。
    对于vertex来说,JanusGraph将会自动创建一个vertices并交由一个新的transaction scope,用户就无需显式声明了。
    graph = JanusGraphFactory.open("berkeleyje:/tmp/janusgraph")
    juno = graph.addVertex() //Automatically opens a new transaction
    graph.tx().commit() //Ends transaction
    juno.property("name", "juno") //Vertex is automatically transitioned
    对于Edge,不会自动创建新的transaction,而且无法在初始transaction之外访问,需要显式创建:

    Transaction Failures

    当提交事务时,由于各种原因,往往不会成功,如因为网络问题,IO问题等。实际上,对于大型系统,事务将会最终失败。
    try {
        if (g.V().has("name", name).iterator().hasNext())
            throw new IllegalArgumentException("Username already taken: " + name)
        user = graph.addVertex()
        user.property("name", name)
        graph.tx().commit()
    } catch (Exception e) {
        //Recover, retry,     or return error message
        println(e.getMessage())
    }
    如果事务执行失败,将会抛出JanusGraphException,失败原因有很多种,可以分为如下两类:
    • Potentially temporary failures
    由于IO,网络原因导致的失败,重试可能成功,且由JanusGraph自动重试,在配置其重试次数。
    • Permanent failures
    产生于完全的网络断开或锁。

    Multi-Threaded Transactions

    JanusGraph通过tinkerpop的transactions支持multi-threaded transaction,通过多线程可以充分利用多核CPU。要开启多线程事务,需要使用createThreadedTx()方法。
    threadedGraph = graph.tx().createThreadedTx();
    threads = new Thread[10];
    for (int i=0; i<threads.length; i++) {
        threads[i]=new Thread({
            println("Do something with 'threadedGraph''");
        });
        threads[i].start();
    }
    for (int i=0; i<threads.length; i++) threads[i].join();
    threadedGraph.tx().commit();
    Concurrent Algorithms
    当实现并发图算法时经常使用createThreadedTx()方法。

    Nested Transactions 嵌套事务

    当在一个事务中逻辑较长时,占有锁的时间也较长,很有可能发生竞争。如下面的情况:
    v1 = graph.addVertex()
    //Do many other things
    v2 = graph.addVertex()
    v2.property("uniqueName", "foo")
    v1.addEdge("related", v2)
    //Do many other things
    graph.tx().commit() // This long-running tx might fail due to contention on its uniqueName lock
    针对此种情况,可以采用在一个短的,嵌套的、线程无关的事务中创建一个顶点,如下示:
    v1 = graph.addVertex()
    //Do many other things
    tx = graph.tx().createThreadedTx()
    v2 = tx.addVertex()
    v2.property("uniqueName", "foo")
    tx.commit() // Any lock contention will be detected here
    v1.addEdge("related", g.V(v2).next()) // Need to load v2 into outer transaction
    //Do many other things
    graph.tx().commit() // Can't fail due to uniqueName write lock contention involving v2

    Common Transaction Handling Problems

    事务不用手动启动,需要手动启动的只有multi-threaded transaction。
    事务是由Tinkerpop的语句自动启动的,但是需要显式的关闭,这种操作很有必要,因为只有使用者知道事务的范围。完成一个事务需要执行g.commit()或g.rollback(),事务将试图从一开始就维护状态,而这很可能导致问题。
    v = g.V(4).next() // Retrieve vertex, first action automatically starts transaction
    g.V(v).bothE()
    >> returns nothing, v has no edges
    //thread is idle for a few seconds, another thread adds edges to v
    g.V(v).bothE()
    >> still returns nothing because the transactional state from the beginning is maintained
    从上面的代码中可以看出,由于事务没有结束,对象的状态得意维持,另外线程的更改没有体现出来。这个问题通常出现在客户端-服务器模式部署的场景下,为了解决此问题,用户需要在执行完毕后手工调用commit()方法。
    v = g.V(4).next() // Retrieve vertex, first action automatically starts transaction
    g.V(v).bothE()
    graph.tx().commit()
    //thread is idle for a few seconds, another thread adds edges to v
    g.V(v).bothE()
    >> returns the newly added edge
    graph.tx().commit()
    在使用multi-threaded事务时,在事务范围内创建的所有的vertices和edges在事务外均不可见,在事务结束后访问这些元素将会导致错误。根据上面展示的,这些element需要在新事务中显示刷新,使用:
    g.V(existingVertex)或者g.E(existingEdge)

    Transaction Configruation

    JanusGraph.buildTransaction()方法给了用户设置和启动multi-threaded transaction的能力,也可以通过JanusGraph.newTransaction()进行设置。
     
    • readOnly()
    • enableBatchLoading()
    • setTimestamp()
    • setVertexCacheSize(long)
    • checkExternalVertexExistence(boolean)
    • checkInternalVertexExistence(boolean)
    • consistencyChecks(boolean)

     

  • 相关阅读:
    CB文件读入后输出中文乱码问题
    2019-ICPC-沈阳站打铁感想
    计蒜客习题:画图游戏(Havel-Hakimi定理)
    计蒜客练习题:接龙(带权并查集)
    搜索----Dungeon Master
    最短路 poj1502 MPI Maelstrom
    poj 3259 Wormholes
    Silver Cow Party
    Til the Cows Come Home
    Cow Contest
  • 原文地址:https://www.cnblogs.com/jiyuqi/p/7150394.html
Copyright © 2011-2022 走看看