2015-09-21 32 views
5

Tôi đang cố gắng sử dụng orientdb (v2.1.2) trong môi trường đa luồng (Java 8), nơi tôi cập nhật một đỉnh từ trong nhiều luồng. Tôi biết rằng orientdb đang sử dụng MVCC và do đó các hoạt động đó có thể bị lỗi và phải được thực thi lại.OrientDB hoạt động biểu đồ đồng thời trong Java

Tôi đã viết một bài kiểm tra đơn vị nhỏ cố gắng kích động các tình huống như vậy bằng cách chờ đợi trên một hàng rào tuần hoàn trong chủ đề ngã ba. Rất tiếc, thử nghiệm không thành công với Ngoại lệ tối nghĩa mà tôi không hiểu:

Sep 21, 2015 3:00:24 PM com.orientechnologies.common.log.OLogManager log 
INFO: OrientDB auto-config DISKCACHE=10,427MB (heap=3,566MB os=16,042MB disk=31,720MB) 
Thread [0] running 
Thread [1] running 
Sep 21, 2015 3:00:24 PM com.orientechnologies.common.log.OLogManager log 
WARNING: {db=tinkerpop} Requested command 'create edge type 'testedge_1442840424480' as subclass of 'E'' must be executed outside active transaction: the transaction will be committed and reopen right after it. To avoid this behavior execute it outside a transaction 
Sep 21, 2015 3:00:24 PM com.orientechnologies.common.log.OLogManager log 
WARNING: {db=tinkerpop} Requested command 'create edge type 'testedge_1442840424480' as subclass of 'E'' must be executed outside active transaction: the transaction will be committed and reopen right after it. To avoid this behavior execute it outside a transaction 
Exception in thread "Thread-4" com.orientechnologies.orient.core.exception.OSchemaException: Cluster with id 11 already belongs to class testedge_1442840424480 
    at com.orientechnologies.orient.core.metadata.schema.OSchemaShared.checkClustersAreAbsent(OSchemaShared.java:1264) 
    at com.orientechnologies.orient.core.metadata.schema.OSchemaShared.doCreateClass(OSchemaShared.java:983) 
    at com.orientechnologies.orient.core.metadata.schema.OSchemaShared.createClass(OSchemaShared.java:415) 
    at com.orientechnologies.orient.core.metadata.schema.OSchemaShared.createClass(OSchemaShared.java:400) 
    at com.orientechnologies.orient.core.metadata.schema.OSchemaProxy.createClass(OSchemaProxy.java:100) 
    at com.tinkerpop.blueprints.impls.orient.OrientBaseGraph$6.call(OrientBaseGraph.java:1387) 
    at com.tinkerpop.blueprints.impls.orient.OrientBaseGraph$6.call(OrientBaseGraph.java:1384) 
    at com.tinkerpop.blueprints.impls.orient.OrientBaseGraph.executeOutsideTx(OrientBaseGraph.java:1739) 
    at com.tinkerpop.blueprints.impls.orient.OrientBaseGraph.createEdgeType(OrientBaseGraph.java:1384) 
    at com.tinkerpop.blueprints.impls.orient.OrientBaseGraph.createEdgeType(OrientBaseGraph.java:1368) 
    at com.tinkerpop.blueprints.impls.orient.OrientBaseGraph.createEdgeType(OrientBaseGraph.java:1353) 
    at com.tinkerpop.blueprints.impls.orient.OrientVertex.addEdge(OrientVertex.java:928) 
    at com.tinkerpop.blueprints.impls.orient.OrientVertex.addEdge(OrientVertex.java:832) 
    at com.gentics.test.orientdb.OrientDBTinkerpopMultithreadingTest.lambda$0(OrientDBTinkerpopMultithreadingTest.java:31) 
    at com.gentics.test.orientdb.OrientDBTinkerpopMultithreadingTest$$Lambda$1/1446001495.run(Unknown Source) 
    at java.lang.Thread.run(Thread.java:745) 

Thử nghiệm đang sử dụng cơ sở dữ liệu trong bộ nhớ đơn giản. Tôi không hiểu tại sao orientdb đang kiểm tra một số hành động cụm:

Cluster with id 11 already belongs to class testedge

Bằng cách nào đó vấn đề này chỉ xuất hiện khi tôi cố gắng để tạo ra hai cạnh có cùng nhãn.

private OrientGraphFactory factory = new OrientGraphFactory("memory:tinkerpop").setupPool(5, 20); 

@Test 
public void testConcurrentGraphModifications() throws InterruptedException { 
    OrientGraph graph = factory.getTx(); 
    Vertex v = graph.addVertex(null); 
    graph.commit(); 
    CyclicBarrier barrier = new CyclicBarrier(2); 

    List<Thread> threads = new ArrayList<>(); 

    // Spawn two threads 
    for (int i = 0; i < 2; i++) { 
     final int threadNo = i; 
     threads.add(run(() -> { 
      System.out.println("Running thread [" + threadNo + "]"); 
      // Start a new transaction and modify vertex v 
      OrientGraph tx = factory.getTx(); 
      Vertex v2 = tx.addVertex(null); 
      v.addEdge("testedge", v2); 
      try { 
       barrier.await(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
      tx.commit(); 
     })); 
    } 

    // Wait for all spawned threads 
    for (Thread thread : threads) { 
     thread.join(); 
    } 
} 

protected Thread run(Runnable runnable) { 
    Thread thread = new Thread(runnable); 
    thread.start(); 
    return thread; 
} 

Các nguồn hoàn chỉnh cho các testcase có thể được tìm thấy ở đây:

https://github.com/Jotschi/orientdb-concurrency-test/blob/master/src/test/java/com/gentics/test/orientdb/OrientDBTinkerpopMultithreadingTest.java#L18

Nói chung tôi sẽ rất biết ơn cho một ví dụ chứng minh làm thế nào để đối phó với các cuộc xung đột MVCC khi sử dụng orientdb trong một môi trường java đa luồng nhúng.


Cập nhật:

tôi nhận thấy rằng vấn đề không còn occures khi tôi tải lại đỉnh trong chủ đề của tôi qua tx.getVertex (vertex.getId()) (không thông qua .reload()) . Tôi nhận được các lỗi khác nhau khi tôi chỉ cần vượt qua các tham chiếu đối tượng đỉnh để thread của tôi và sử dụng nó ở đó. Tôi cho rằng lớp OrientVertex không phải là luồng an toàn.

Trả lời

4
  1. Bạn đang ở bên phải tất cả các yếu tố đồ thị không phải là chủ đề an toàn.
  2. Lý do ngoại lệ của bạn sau khi bạn tạo cạnh, bạn bên dưới cơ sở dữ liệu biểu đồ tạo tài liệu với lớp tương đương với nhãn của cạnh. Nếu lớp là giao dịch vắng mặt được cam kết tự động và lớp mới bên trong lược đồ được tạo ra. Mỗi lớp được ánh xạ tới cụm trong cơ sở dữ liệu (nó giống như một bảng) khi bạn thêm các cạnh đồng thời bạn cùng một lúc tạo cùng một lớp và kết quả là cùng một cụm được tạo ra. Vì vậy, một thread thắng khác không thành công với ngoại lệ mà cụm với tên đã được tạo ra. Trên thực tế tôi đề nghị bạn tạo tất cả các lớp aka nhãn của các cạnh nếu có thể trước khi bạn sẽ thêm các cạnh khi chạy.

Một đề xuất khác. Bạn nên suy nghĩ về thể hiện OrientGraph như thể nó đang kết nối đến máy chủ. Việc sử dụng tốt nhất là sau:

  1. Cài đặt hồ bơi trong OrientGraphFactory
  2. Acquire graph dụ trước khi giao dịch.
  3. Thực hiện giao dịch.
  4. Gọi .shutdown(), không tạo trường hợp đồ thị sống lâu.
Các vấn đề liên quan