内存配置

本页面介绍了 Neo4j 内存配置和使用的各个方面。Neo4j 服务器的 RAM 有多个使用区域,其中一些区域有子区域

neo4j memory management
图 1. Neo4j 内存管理
操作系统内存

必须为运行操作系统本身的进程保留一些内存。无法显式配置应为操作系统保留的 RAM 量,因为这是在配置 Neo4j 后剩余的 RAM。

对于专门用于运行 Neo4j 的服务器,1GB 是一个不错的起点。但是,在某些情况下,为操作系统保留的内存量明显大于 1GB,例如内存特别大的服务器。

如果您没有为操作系统留出足够的可用空间,它将开始将内存交换到磁盘,这会严重影响性能。因此,通常建议为 Neo4j 专用服务器关闭交换功能。

JVM 堆

JVM 堆是 Neo4j 用于存储实例化 Java 对象的单独动态内存分配。Java 对象的内存由垃圾收集器自动管理。特别重要的是垃圾收集器会自动处理未使用的对象的删除。有关垃圾收集器工作方式以及如何对其进行调优的更多信息,请参阅垃圾收集器调优.

堆内存大小由参数 server.memory.heap.initial_sizeserver.memory.heap.max_size 确定。建议将这两个参数设置为相同的值,以避免不必要的完全垃圾回收暂停。

通常,为了提高性能,您应该配置足够大的堆来维持并发操作。

本机内存

原生内存,有时也称为堆外内存,是由 Neo4j 直接从操作系统分配的内存。此内存会根据需要动态增长,不受垃圾收集器的影响。

DBMS

数据库管理系统(DBMS)包含 Neo4j 实例的全局组件。例如,bolt 服务器、日志服务、监控服务等。

数据库

系统中的每个数据库都有开销。在具有多个数据库的部署中,需要考虑此开销。

事务

执行事务时,Neo4j 会将尚未提交的数据、结果以及查询的中间状态保存在内存中。为此所需的内存大小高度依赖于 Neo4j 使用方式的性质。例如,长时间运行的查询或非常复杂的查询可能需要更多内存。事务的某些部分可以选择性地放置在堆外,但为了获得最佳性能,建议将所有内容保留在堆内。

可以通过设置 dbms.memory.transaction.total.max 来限制此内存组。

页面缓存

页面缓存用于缓存存储在磁盘上的 Neo4j 数据。将图形数据和索引缓存到内存中可以避免代价高昂的磁盘访问,并带来最佳性能。

用于指定 Neo4j 允许用于页面缓存的内存量的参数是:server.memory.pagecache.size

网络缓冲区

Neo4j 使用直接缓冲区来发送和接收数据。直接字节缓冲区对于提高性能很重要,因为它们允许本机代码和 Java 代码共享数据而不进行复制。但是,创建它们很昂贵,这意味着字节缓冲区在创建后通常会被重用。

其他共享缓冲区

这包括未指定的共享直接缓冲区。

JVM 开销

JVM 需要一些内存才能正常运行。例如,这可以是

  • 线程堆栈 - 每个线程都有自己的调用堆栈。堆栈存储原始局部变量和对象引用以及调用堆栈(方法调用列表)本身。堆栈在堆栈帧移出上下文时被清除,因此此处不会执行 GC。

  • 元空间 - 元空间存储 java 类定义和其他元数据。

  • 代码缓存 - JIT 编译器将生成的本机代码存储在代码缓存中,通过重用代码来提高性能。

有关 JVM 使用的内存的更多详细信息和限制方法,请参阅您的 JVM 文档。

注意事项

始终使用显式配置

为了更好地控制系统行为,建议始终在 neo4j.conf 中显式定义页面缓存和堆大小参数。否则,Neo4j 会在启动时根据可用系统资源计算一些启发式值。

初始内存推荐

使用 neo4j-admin server memory-recommendation 命令获取有关如何分配一定内存量的初始建议。可能需要调整这些值以适应每个特定的用例。

检查 DBMS 中所有数据库的内存设置

neo4j-admin server memory-recommendation 命令对于检查当前数据和索引的分布很有用。

示例 1. 使用 neo4j-admin server memory-recommendation 检查所有数据库的内存设置

估计数据库文件的大小。

bin/neo4j-admin server memory-recommendation
...
...
...
# Total size of lucene indexes in all databases: 6690m
# Total size of data and native indexes in all databases: 17050m

您可以看到 Lucene 索引大约占用了 6.7GB 的数据,数据量和原生索引加起来大约占用了 17GB。

使用这些信息,您可以对内存配置进行完整性检查

  • 将数据量和原生索引的值与 server.memory.pagecache.size 的值进行比较。

  • 对于使用堆外事务状态的情况,估计事务工作负载以及在分配 server.memory.pagecache.sizeserver.memory.heap.initial_size 后剩下的内存量。

  • 将 Lucene 索引的值与分配 server.memory.pagecache.sizeserver.memory.heap.initial_size 后剩下的内存量进行比较。

在一些生产系统中,对内存的访问是有限的,并且必须在不同的区域之间进行协商。因此,建议对这些设置进行一定量的测试和调整,以找出可用内存的最佳分配方式。
限制事务内存使用建议

所有事务的测量堆使用量只是一个估计值,实际的堆利用率可能略大于或略小于估计值。在某些情况下,估计算法在内存图的更深层次上检测共享对象的限制可能会导致高估。这是因为基于对内存使用量的聚合估计给出了保守的估计,其中所有贡献对象的标识都未知,并且不能假定为共享。例如,当您在非常大的列表上使用 UNWIND 或扩展可变长度或最短路径模式时,其中许多关系在计算结果路径之间共享。

在这些情况下,如果您遇到查询被终止的问题,您可以使用 事务内存限制 禁用执行相同的查询。如果实际堆使用量不太大,它可能会成功完成而不会触发内存不足错误。

容量规划

在许多用例中,尝试尽可能多地缓存数据和索引是有利的。以下示例说明了估计页面缓存大小的方法,具体取决于您是在生产中运行还是计划未来的部署。

示例 2. 估计现有 Neo4j 数据库的页面缓存

首先,估计数据和索引的总大小,然后乘以某个因子(例如 20%),以允许增长。

bin/neo4j-admin server memory-recommendation
...
...
...
# Total size of lucene indexes in all databases: 6690m
# Total size of data and native indexes in all databases: 35050m

您可以看到,数据量和原生索引加起来大约占用了 35GB。在您的特定用例中,您估计 20% 将提供足够的增长空间。

server.memory.pagecache.size = 1.2 * (35GB) = 42GB

通过将以下内容添加到 neo4j.conf 中来配置页面缓存

server.memory.pagecache.size=42GB
示例 3. 估计新 Neo4j 数据库的页面缓存

在计划未来的数据库时,使用一小部分数据运行导入很有用,然后将生成的存储大小增量乘以该分数加上某个增长百分比。

  1. 运行 memory-recommendation 命令以查看所有当前数据库中数据和索引的总大小。

    bin/neo4j-admin server memory-recommendation
    ...
    ...
    ...
    # Total size of lucene indexes in all databases: 6690m
    # Total size of data and native indexes in all databases: 35050m
  2. 导入 1/100 的数据,然后再次测量所有数据库的数据量和原生索引。

    bin/neo4j-admin server memory-recommendation
    ...
    ...
    ...
    # Total size of lucene indexes in all databases: 6690m
    # Total size of data and native indexes in all databases: 35400m

    您可以看到,数据量和原生索引加起来大约占用了 35.4GB。

  3. 将生成的存储大小增量乘以该分数。

    35.4GB - 35GB = 0.4GB * 100 = 40GB

  4. 将该数字乘以 1.2 以放大结果,并允许 20% 的增长。

    server.memory.pagecache.size = 1.2 * (40GB) = 48GB

  5. 通过将以下内容添加到 neo4j.conf 中来配置页面缓存

    server.memory.pagecache.size=48G

限制事务内存使用量

通过使用 dbms.memory.transaction.total.max 设置,您可以为服务器上运行的所有事务配置全局最大内存使用量。此设置必须配置得足够低,以避免内存不足。如果您在高事务负载期间遇到 OutOfMemory 消息,请尝试降低此限制。

Neo4j 还提供以下设置以提供公平性,这有助于提高多租户部署的稳定性。

当任何限制达到时,事务将被终止,而不会影响数据库的整体运行状况。

为了帮助您配置这些设置,您可以使用以下命令列出当前使用情况

CALL dbms.listPools()
SHOW TRANSACTIONS

或者,您也可以在 query.log 中监控每个查询的内存使用量。