知识库

预热缓存以提高冷启动性能

注意:对于 3.5.x 及更高版本,以下详细信息不再适用,因为 Neo4j 将始终记录页面缓存中的内容,并且在 Neo4j 重启后,页面缓存将自动使用先前在页面缓存中的数据进行预热。在 3.5.x 及更高版本中,logs\debug.log 将报告类似内容

2020-12-14 21:00:08.486+0000 INFO [o.n.k.i.p.PageCacheWarmer] Page cache warmup started.
2020-12-14 21:00:08.659+0000 INFO [o.n.k.i.p.PageCacheWarmer] Page cache warmup completed. 441 pages loaded. Duration: 173ms.

注意:对于 Neo4j 2.3+ 版本,不再有对象缓存,因此这会预热将 Neo4j 存储文件映射到内存中的页面缓存。

您可能会发现某些查询在第二次运行时速度会快很多。这是因为在冷启动时,服务器节点尚未缓存任何内容,需要从磁盘获取所有记录。一旦部分/全部记录被缓存,您将看到性能显著提升。

一种广泛采用的技术是“预热缓存”。最基本的方法是,我们运行一个查询,触及图中的每个节点和关系。假设数据存储可以完全载入内存,这将缓存整个图。否则,它将尽可能多地进行缓存。尝试一下,看看它如何帮助您!

Cypher (服务器,Shell)
MATCH (n)
OPTIONAL MATCH (n)-[r]->()
RETURN count(n.prop) + count(r.prop);

在上面的示例中,对 count(n.prop) + count(r.prop) 的引用被用来强制优化器搜索具有名为“prop”属性的节点/关系。将其替换为 count(*) 将不足够,因为它不会加载所有节点和关系的属性。

嵌入式 (Java)
@GET @Path("/warmup")
public String warmUp(@Context GraphDatabaseService db) {
  try ( Transaction tx = db.beginTx()) {
    for ( Node n : GlobalGraphOperations.at(db).getAllNodes()) {
      n.getPropertyKeys();
      for ( Relationship relationship : n.getRelationships()) {
        relationship.getPropertyKeys();
        relationship.getStartNode();
      }
    }
  }
  return "Warmed up and ready to go!";
}

从 3.0 版本起,随着 APOC 的加入,现在可以通过运行存储过程来预热缓存

CALL apoc.warmup.run()

这可以在许多方面提供帮助。除了纯粹的性能提升,它还可以帮助缓解因查询滞后而导致的上游问题。例如,如果节点繁忙,并且您的负载均衡器/代理的超时时间非常短,那么在图尚未完全加载到内存中时,集群可能会在初始阶段显得不可用。如果缓存已预热,那么在集群冷启动时,短超时将不再是问题。

© . All rights reserved.