1

我在 Neo4j 中遇到了一个奇怪的问题。我最近一直在使用 GraphAware TimeTree 并填充它直到昨天进展顺利。由于我犯了一个错误,我不得不重建树,所以我让一个脚本在一夜之间运行(nohup)。

今天回来发现我的脚本只跑了3分钟!

$ ps aux | grep timetreepop
root     21840  0.0  0.0 195952  2816 ?        S    Jul28   0:00 sudo nohup python timetreepop.py
root     21841  0.0  0.2 381416 75016 ?        S    Jul28   0:03 python timetreepop.py

我在工作时注意到了这种行为,但我认为在我不活动时将其放置一夜会有所帮助。如果可能发生争用,我还关闭了我的其他 java 服务器进程。在这一点上,我的服务器只会在后台运行一个 python 龙卷风服务器,它不是很庞大,并且不会获得太多流量(一天几次点击)。

总而言之,我的系统中有大量可用的 RAM,CPU 没有在其他地方使用,并且没有其他进程在我的机器上运行大量 IO。使用top/atop显示具有可用资源的健康系统。

这是我的脚本正在执行的高级操作:

neo = neopop.handler()
for i, meta_id in enumerate(meta_gen(ship='KAOU')):
   neo.populate_timetree(record=meta_id)

我的处理程序在构造函数中创建驱动程序和会话__init__

self.driver = graphdb.driver(config.NEO4J_HTTP_LINK)
self.session = self.driver.session()

我的生成器提供meta_id的值是图表中节点中的唯一属性值。

populate_timetree()函数创建以下语句:

MATCH (r:record {meta:"KAQP_20120101v20001_0001"}) WITH r 
CALL ga.timetree.events.attach({node: r, time: r.time, relationshipType: "observedOn", resolution:"Minute"})
YIELD node RETURN node.meta;

一切都很好,我第一次去。在弄乱了我的时间值之后,我删除了数据库,重新启动,然后再试一次。只有这一次,当我调用关闭会话时,我的程序会冻结:

neo.session.close()

注意:我实际上在我的__del__解构器中调用它,(我知道这可能被认为是不好的做法,但到​​目前为止它一直对我有用并且适合我的需要。)

我已经仔细检查了我所有的代码是否有恶意的 readline 语句/任何可能导致它暂停的东西。还重新编译了我的包,其中包含所有这些代码。我知道事实上它被困在这个session.close()声明中。

所以我尝试使用 Neo4j-shell 工具来看看是否有什么不同。首先是快速响应检查:

$ neoc 'schema'
Indexes
  ON :record(meta) ONLINE (for uniqueness constraint) 

Constraints
  ON (record:record) ASSERT record.meta IS UNIQUE

好的,一切都好。现在我尝试使用 timetree 调用单个值:

$ ./neo4j-shell -c '
> MATCH (r:record {meta:"KAOU_20110613v20001_0000"}) WITH r 
> CALL ga.timetree.events.attach({node: r, time: r.time, relationshipType: "observedOn", resolution:"Minute"})
> YIELD node RETURN node.meta;
> '

繁荣。Neo4j 卡住了!需要明确的是,我知道 MATCH 语句不会永远在这里,因为我这次只在我的数据库中放入了大约 200 万个节点,并且单独调用 match 语句运行得非常好。我什至为这个独特的属性设置了一个索引(参见上面的模式调用)。

那么这里发生了什么?如果我只插入一个节点,我认为树的初始创建应该不是太大的问题。我的第一次尝试似乎完美无缺。我不确定这次我做了什么不同,除了用我拥有的 5800 万条记录中的 200 万条填充我的数据库。(所以它应该更快)。

实际上,我让这个命令运行了几个小时,而且它在我的系统上也只运行了几分钟。我对这里发生的事情感到非常困惑。有没有人有任何想法?无论如何我可以看到neo4j正在积极地处理这个命令吗?(请记住,我使用的是社区版)

我在 CentOS 7 服务器上运行 neo4j 的 3.0.3 版本和 3.0.3.39 timetree / graphaware。

我唯一的想法是,我一直在调用 cypher 语句并在它们提交这么多次之前取消它们,无论是通过 python 还是命令行 shell 工具。通过在完成之前取消大交易,我是否有可能过多地与交易管理器混淆?

例如:

/neo4j-shell -c 'MATCH (r:record) CALL ga.timetree.events.attach(....) ....'

然后control-C在它运行了大约2个小时后没有完成。


更新:

好的,所以我调查了我的日志文件并发现了一些问题。由于内存不足,我的线程似乎被阻塞了。我猜我的最大堆大小受到人为限制,并且没有使用我机器上的可用资源。(也许??)。所以我手动设置dbms.memory.heap.max_size=16000.

现在问题似乎消失了!我想我很困惑,因为我希望 Java OOM 出现在neo4j-shell工具的响应中,而不是像取得进展一样空转。

4

1 回答 1

1
$ ./neo4j-shell -c '
> MATCH (r:record {meta:"KAOU_20110613v20001_0000"}) WITH r 
> CALL ga.timetree.events.attach({node: r, time: r.time, relationshipType: "observedOn", resolution:"Minute"})
> YIELD node RETURN node.meta;
> '

该查询预计将附加多少个节点到时间树?

此过程不使用批处理,因此它仅限于您的内存可以在单个事务中执行的操作(这现在在我们的积压工作中)。

也就是说,手动将事件附加到树上通常没有意义,此过程是为了方便起见,但我们建议使用自动事件附件:

https://github.com/graphaware/neo4j-timetree#automatic-event-attachment

这样,重新附加完整的数据库(或仅配置为附加的节点)将是重新启动数据库的问题,并且此过程将使用批处理事务运行,这将显着加快所花费的时间。

于 2016-07-29T17:56:51.080 回答