知识库

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

注意: 对于 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()

这可以在很多方面提供帮助。除了纯粹的性能提升外,它还可以帮助缓解因查询滞后导致的上游问题。例如,如果节点繁忙,而你的负载均衡器/代理设置了非常短的超时时间,那么在集群刚启动且图尚未加载到内存时,可能会出现集群不可用的情况。如果缓存已预热,短超时在冷启动的集群上就不应成为问题。

© . This site is unofficial and not affiliated with Neo4j, Inc.