【问题标题】:write lock behavior in neo4j cypher over transational REST api通过事务性 REST api 在 Neo4j 密码中写入锁定行为
【发布时间】:2015-08-03 23:25:08
【问题描述】:

我正在使用如下所示的 CYPHER(使用 Neo4j 2.2.3,通过事务密码 REST 端点)以原子方式读取和增加节点上的计数器属性:

MATCH node WHERE id(node)={nodeId}
SET node.counter=COALESCE(node.counter,0) + 1
RETURN node.counter

我有多个线程发布这样的 REST 帖子,我现在看到两个线程返回相同的计数器值的情况。

此行为类似于此处描述的从 2.1 到 2.2 的可能回归:Neo4j 2.2 Cypher locking regression?

但是,之前有人建议这在 CYPHER 中是不可能的(请参阅此处的 cmets:https://stackoverflow.com/a/18486645)......甚至更早之前它似乎是可能的(请参阅:https://stackoverflow.com/a/18450171

当有多个并发的 REST POST 查询时,是否有一个类似于上面的 CYPHER 查询能够可靠地产生唯一的(单调递增的)计数器值?

【问题讨论】:

    标签: multithreading rest neo4j cypher


    【解决方案1】:

    在 Neo4j 中,您需要在读取和更新值之前获得写锁。我们在单个事务(一个 REST 调用)中作为两个语句来执行此操作。我们使用 MERGE/ON CREATE/ON MATCH,但我认为这不是必要的,甚至在您的情况下也不会起作用。我相信这应该对你有用。

    声明 1:

    MATCH node WHERE id(node)={nodeId}
    SET node.__lock=true
    RETURN node.__lock
    

    语句 2:

    MATCH node WHERE id(node)={nodeId}
    SET node.counter=COALESCE(node.counter,0) + 1
    SET node.__lock=false
    RETURN node.counter
    

    【讨论】:

    • 谢谢@sean-timm。我会试试这个。现在我明白了为什么在问题 31755509 中使用了 2 语句结构(参见上面 Q 中的链接)。但我也想知道您是否在 2.2.x 版本中看到了像 31755509 中所述的任何不良行为?
    • 请参阅此要点,该要点显示了我尝试此操作时的密码 json 输入和输出:gist.github.com/cjdaly/aa5334b58c34eeff85fa。您是否收到此类错误,然后重试操作?或者这不是您希望看到的?
    • 我不希望得到那个错误。该错误听起来像是您在写入的同时在 Neo4j 中创建了一个约束。您是否总是遇到同样的错误?
    • 我们在 Neo4j 2.2.0 Enterprise 中使用这种模式没有问题。
    • 我正在使用“社区”版下载,v. 2.2.3。我正在使用与计数器增量并行执行的“CREATE CONSTRAINT”,因此就当前支持的内容而言,我似乎超出了界限。我要将此答案标记为正确,因为我认为您解释了如何拆分为 2 个语句是正确的一般方法(nitpick:在语句 1 中,RETURN node.__lock)。目前,在我的应用程序中,我实际上已经序列化了所有 neo4j REST 流量,并且一切运行顺利。我的下一个计划是尝试序列化写入并让读取并行......
    【解决方案2】:

    简短的解决方案是:

    MATCH node WHERE id(node)={nodeId}
    SET 
      node.__lock=true, 
      node.counter=COALESCE(node.counter,0) + 1,
      node.__lock=false
    RETURN node.counter
    

    这是 Sean Timm 的改进解决方案。 这种表示法比两次交易更有效(更快)

    【讨论】:

      【解决方案3】:

      除了@SeanTimm 的回答之外,如果您使用流行的(和开源的)APOC plugin for Neo4j,您可以通过 Cypher 显式锁定节点。 APOC 有一系列可以通过 Cypher 调用的显式锁定过程,例如 call apoc.lock.nodes([nodes])

      如果您可以使用此选项,它可能比其他一些老套的解决方案更可取。

      通过neo4j-contrib.github.io/neo4j-apoc-procedures/#_locking了解更多信息

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-05
        • 2020-02-07
        • 1970-01-01
        相关资源
        最近更新 更多