【问题标题】:find-or-create vs. multi-threading with Neo4j使用 Neo4j 查找或创建与多线程
【发布时间】:2014-01-20 20:34:31
【问题描述】:

在我的基于 Neo4j 的应用程序中,我有一个经典的查找或创建用例:我询问 neo4j 是否已经存在与其他节点具有特殊关系的节点。如果没有,那么我将在同一事务中创建一个。没什么特别的...但是如果我将此方法称为多线程(或连接到同一个数据库的 n 个客户端),那么有时我会遇到一个异常,指出有多个元素与我的查询匹配。这意味着在不久之前有两个线程都创建了相同的“对”节点。 Java 级别的同步不是一种选择(因为请求可以来自多个客户端/服务器)。

除了捕获异常并删除重复的节点之外,我该如何解决这些问题?

我使用 Spring Data Neo4j 2.3.3 和 Neo4j 1.9.5。

这是我的查询:

START expected=node({0}), actual=node({1}) MATCH (expected)<-[:EXPECTED]- (pair) -[:ACTUAL]->(actual) RETURN pair

顺便说一句。在这种情况下抛出的异常是NoSuchElementException,至少对我来说这有点令人困惑。

WARN  [00:32.31,962] de.xxx.web.AbstractExceptionHandlers: error.NoSuchElementException
java.util.NoSuchElementException: More than one element in org.neo4j.cypher.PipeExecutionResult$$anon$1@8f0dc23. First element is '{pair=Node[20001]}' and the second element is '{pair=Node[20000]}'
    at org.neo4j.helpers.collection.IteratorUtil.singleOrNull(IteratorUtil.java:122)
    at org.neo4j.helpers.collection.IteratorUtil.singleOrNull(IteratorUtil.java:289)
    at org.springframework.data.neo4j.conversion.QueryResultBuilder$1.singleOrNull(QueryResultBuilder.java:94)
    at org.springframework.data.neo4j.repository.query.GraphRepositoryQuery.dispatchQuery(GraphRepositoryQuery.java:108)
    at org.springframework.data.neo4j.repository.query.GraphRepositoryQuery.execute(GraphRepositoryQuery.java:81)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:337)
    at org.springframework.aop.framework.ReflectiveMethodvocation.proceed(ReflectiveMethodvocation.java:172)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithvocation(TransactionInterceptor.java:96)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
    at org.springframework.aop.framework.ReflectiveMethodvocation.proceed(ReflectiveMethodvocation.java:172)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
    at org.springframework.aop.framework.ReflectiveMethodvocation.proceed(ReflectiveMethodvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
    at com.sun.proxy.$Proxy63.findByAttributes(Unknown Source)
    at de.xxx.core_service.attribute.AttributeManagerImpl.findOrCreatePair_aroundBody32(AttributeManagerImpl.java:212)
    at de.xxx.core_service.attribute.AttributeManagerImpl$AjcClosure33.run(AttributeManagerImpl.java:1)

【问题讨论】:

  • 您可能还应该分享您的实体代码和用法。

标签: multithreading neo4j spring-data-neo4j


【解决方案1】:

您必须为此手动锁定,否则您会进入典型的竞争条件。

锁定有问题的两个节点可能最简单。

Neo4j Transaction 上有一个锁管理 API,但您也可以只删除一个不存在的属性,该属性也需要一个写锁。

我们可能不得不在某个时候公开 SDN 中的锁定。 如果您认为这是个好主意,请提出 JIRA 问题。

【讨论】:

  • 感谢 Micha 的及时回复。这很有帮助,我会试试这个。但这让我想到了另一点:正如我在上面所写的,我使用 SDN,因此我无法直接访问底层节点。因此,我必须使用 Neo4jTemplate 来查询底层节点并使用本机 Neo4J-API 来删除(不存在的)属性,如获取锁的建议。我对吗?如果是这样,我还将向 SDN 提出功能请求,以便能够将底层节点映射到我的实体实例(这在其他用例中也可能会有所帮助)。
猜你喜欢
  • 2017-02-27
  • 2013-12-17
  • 2013-05-26
  • 1970-01-01
  • 2018-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-05
相关资源
最近更新 更多