简体   繁体   English

Neo4j 死锁

[英]Neo4j Deadlocks

I'm implementing a Neo4j client for BG benchmark .我正在为BG benchmark实施 Neo4j 客户端。 There are 11 functions, simulating 11 different social networking actions.有11个功能,模拟11种不同的社交网络动作。 Each of these functions has its own transaction body.这些函数中的每一个都有自己的事务主体。 But when I'm running with 100 threads, sometimes it throws deadlock detection exception.但是当我运行 100 个线程时,有时会抛出死锁检测异常。

I have users as nodes and friendships as relationships.我有用户作为节点和友谊作为关系。 I have invite friend, reject friend, accept friend and thaw friendship which all have two users as their input.我有邀请朋友,拒绝朋友,接受朋友和解冻友谊,它们都有两个用户作为他们的输入。 The way they're working is that they're getting all relationships of one user node and find the relationship with the other user node.他们的工作方式是获取一个用户节点的所有关系并找到与另一个用户节点的关系。

Is any one aware of locking mechanism of Neo4j?有人知道 Neo4j 的锁定机制吗?

You can read about the deadlocks in the Neo4j documentation .您可以在Neo4j 文档中阅读有关死锁的信息 These can appear when you have concurrent modifications of the same entities (nodes or relationships).当您对相同的实体(节点或关系)进行并发修改时,这些可能会出现。 Note that when modifying a entity, several locks may be used: for instance for a relationship, the locks on the two nodes connected by the relationship are taken.请注意,在修改实体时,可能会使用多个锁:例如,对于一个关系,使用该关系连接的两个节点上的锁。

Default locking behaviour:默认锁定行为:

  1. When adding, changing or removing a property on a node or relationship a write lock will be taken on the specific node or relationship.在节点或关系上添加、更改或删除属性时,将对特定节点或关系进行写锁定。
  2. When creating or deleting a node a write lock will be taken for the specific node.创建或删除节点时,将为特定节点获取写锁。
  3. When creating or deleting a relationship a write lock will be taken on the specific relationship and both its nodes.创建或删除关系时,将对特定关系及其两个节点进行写锁定。

The locks will be added to the transaction and released when the transaction finishes.锁将被添加到事务并在事务完成时释放。

  1. Design database in a way that minimum locking will be there.以最小锁定的方式设计数据库。
  2. Avoid using same nodes and relationships are used by many users at same instance.避免使用相同的节点和关系被多个用户在同一实例中使用。 Keep minimum transaction period for those nodes and relationships.保持这些节点和关系的最短交易周期。

Maybe serializing the parallel writing query would be helpful to your solution.也许序列化并行写入查询会对您的解决方案有所帮助。 In your situation, You have 11 functions, simulating 11 different social networking actions.在您的情况下,您有 11 个功能,模拟 11 种不同的社交网络操作。 In your description, I thought that some of the actions(transactions) may be executed in sequential order (e,g, you can only accept friend request after your friend sent an invitation).在您的描述中,我认为某些操作(交易)可能会按顺序执行(例如,您只能在您的朋友发送邀请后接受好友请求)。 You may serialize some write transactions.您可以序列化一些写入事务。 In other words, some queries will be blocked until the previous ones finished.换句话说,一些查询将被阻塞,直到前一个查询完成。 With the help of Causal chaining and bookmarks, you can serialize the operations for each session.在因果链和书签的帮助下,您可以序列化每个会话的操作。 For example, if you have three functions, sendInvitationToFriend , reject friend , acceptFriend .举例来说,如果你有三个功能, sendInvitationToFriendreject friendacceptFriend reject/accept transactions will be blocked until the sendInvitationToFriend transaction finished.拒绝/接受交易将被阻止,直到 sendInvitationToFriend 交易完成。

Some code snippets (neo4j-java-driver 4.1) :一些代码片段(neo4j-java-driver 4.1):


    List<Bookmark> bookmarks = new ArrayList<>();

    // Send Invitation.
    try ( Session session = driver.session( builder().withDefaultAccessMode( AccessMode.WRITE ).build())){
        session.writeTransaction( tx -> this.sendInvitationToFriend( tx, "friendId", "yourId"));
        savedBookmarks.add(session.lastBookmark() );
    }

    // accept the invitation 
    try (Session session = driver.session( builder().withDefaultAccessMode( AccessMode.WRITE ).withBookmarks( savedBookmarks ).build())){
        session.writeTransaction( tx -> this.acceptFriend(tx, "friendId", "yourId"));
    }

    // Create a friendship between the two people created above.
    try (Session session = driver.session(builder().withDefaultAccessMode( AccessMode.WRITE).withBookmarks(savedBookmarks ).build())) {
        session.writeTransaction( tx -> this.rejectFriend( tx, "friendId", "yourId"));
    }

You also mentioned that your simulation is somehow random.您还提到您的模拟在某种程度上是随机的。 My suggestion you could define a retry strategy in your program, re-attempt the query serval times until it goes well and let the main thread to sleep for a while between any two retries.我的建议是你可以在你的程序中定义一个重试策略,重新尝试查询 serval 时间,直到它运行良好,让主线程在任何两次重试之间休眠一段时间。 You can find more details information from the link您可以从链接中找到更多详细信息

Wish this post will be helpful to you.希望这篇文章对你有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM