内存配置
本页面描述了 Neo4j 内存配置和使用的不同方面。Neo4j 服务器的 RAM 具有多个使用区域,其中包含一些子区域。
- 操作系统内存
-
必须为操作系统自身的运行进程保留一些内存。无法明确配置应为操作系统保留的 RAM 量,因为这是在配置 Neo4j 后仍然可用的 RAM。
对于专用于运行 Neo4j 的服务器来说,1GB 是一个很好的起始点。然而,在某些情况下,为操作系统保留的内存量会显著大于 1GB,例如内存容量异常大的服务器。
如果您有向量索引,则需要确保操作系统为向量索引预留了足够的内存以使其最佳运行,因为向量索引加载在操作系统内存中,而不是 Neo4j 页面缓存中。有关更多信息,请参阅向量索引内存配置。
如果您没有为操作系统留下足够的空间,它将开始将内存交换到磁盘,这将严重影响性能。因此,通常建议为 Neo4j 专用服务器关闭交换空间。
- JVM 堆
-
JVM 堆是 Neo4j 用于存储实例化 Java 对象的独立动态内存分配。Java 对象的内存由垃圾收集器自动管理。特别重要的是,垃圾收集器会自动处理未使用对象的删除。有关垃圾收集器如何工作以及如何对其进行调优的更多信息,请参阅垃圾收集器调优。
堆内存大小由参数
server.memory.heap.initial_size
和server.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 将需要一些内存才能正常运行。例如,这可以是
-
线程栈 – 每个线程都有自己的调用栈。栈存储原始局部变量和对象引用以及调用栈(方法调用列表)本身。当栈帧超出上下文时,栈会被清理,因此这里不会执行垃圾回收。
-
元空间 – 元空间存储 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
的值进行比较。 -
在使用堆外事务状态的情况下,估算事务工作负载以及
dbms.tx_state.max_off_heap_memory
的剩余内存量。 -
将 Lucene 索引的值与分配
server.memory.pagecache.size
和server.memory.heap.initial_size
后剩余的内存量进行比较。
在某些生产系统中,内存访问受限,必须在不同区域之间进行协商。因此,建议对这些设置进行一定量的测试和调优,以找出可用内存的最佳划分。 -
容量规划
在许多用例中,尽可能多地缓存数据和索引是有利的。以下示例说明了估算页面缓存大小的方法,具体取决于您是已在生产环境中运行还是正在规划未来的部署
首先,估算数据和索引的总大小,然后乘以某个系数,例如 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
在规划未来的数据库时,使用一部分数据运行导入,然后将结果存储大小增量乘以该部分加上一定的增长百分比,这会很有用。
-
运行
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
-
导入 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。
-
将结果存储大小增量乘以该分数。
35.4GB - 35GB = 0.4GB * 100 = 40GB
-
将该数字乘以 1.2 以扩大结果,并允许 20% 的增长。
server.memory.pagecache.size
= 1.2 * (40GB) = 48GB -
通过将以下内容添加到 neo4j.conf 来配置页面缓存
server.memory.pagecache.size=48G
限制事务内存使用
通过使用 dbms.memory.transaction.total.max
设置,您可以配置服务器上所有运行事务的全局最大内存使用量。此设置必须配置得足够低,以避免内存不足。如果在高事务负载期间遇到 OutOfMemory
消息,请尝试降低此限制。
Neo4j 还提供了以下设置以提供公平性,这有助于提高多租户部署的稳定性。
-
设置
db.memory.transaction.total.max
限制每个数据库的事务内存使用量。 -
设置
db.memory.transaction.max
限制每个事务。
当达到任何限制时,事务将被终止,而不会影响数据库的整体健康状况。
为帮助配置这些设置,您可以使用以下命令列出当前使用情况
CALL dbms.listPools()
SHOW TRANSACTIONS
或者,您可以在 query.log 中监控每个查询的内存使用情况。