跳转到主要内容

集群基础调优

本文档提供了关于 Apache Druid 部署性能调优相关的配置属性和集群架构考量的基本指导原则。

请注意,本文档提供的是一般性指导原则和经验法则:它们并非集群调优的绝对、普适规则。本入门指南也并未详尽描述所有 Druid 调优属性,完整的属性描述请参考 配置参考手册

如果您有关于特定用例的 Druid 调优问题,或对本指南未涵盖的配置属性有疑问,请咨询 Druid 用户邮件列表或其他社区渠道

进程特定指南

Historical

堆大小调整

Historical 节点堆内存消耗的主要来源是:

  • 来自数据段(segments)的部分未合并查询结果。
  • 用于 查找(Lookups) 的存储映射。

估算 Historical 堆大小的一个通用经验法则是:(0.5GiB * CPU 核心数)

这是一个起点,而非 Historical 堆大小的硬性规定。请注意,对于某些垃圾回收器,过大的堆可能会导致过长的 GC 停顿。对于超过约 24GiB 的堆,我们建议使用能够处理大堆的回收器,如 Shenandoah 或 ZGC。

如果启用了 Historical 缓存,缓存将存储在堆中,大小由 druid.cache.sizeInBytes 设定。

Historical 节点堆内存不足可能意味着配置错误或使用模式导致集群负载过重。

查找表(Lookups)

如果您正在使用查找功能,请计算所加载查找映射的总大小。

Druid 在更新查找映射时执行原子交换(交换期间旧映射和新映射将同时存在于堆中),因此查找映射产生的最大潜在堆内存使用量为 (2 * 所有加载查找的总大小)。

请务必在 (0.5GiB * CPU 核心数) 的准则基础上,再加上 (2 * 所有加载查找的总大小) 作为您的堆大小。

处理线程与缓冲区

请参阅 处理线程与缓冲区的通用指南 一节,了解处理线程/缓冲区配置的概述。

关于 Historical 节点:

  • druid.processing.numThreads 通常应设置为 (核心数 - 1):较小的值可能导致 CPU 利用率不足,而超过核心数则可能导致不必要的 CPU 争用。
  • druid.processing.buffer.sizeBytes 可以设置为 500MiB。
  • druid.processing.numMergeBuffers,对于一般用途,合并缓冲区与处理线程的比例为 1:4 是一个合理的选择。

直接内存(Direct Memory)大小调整

上述的处理缓冲区和合并缓冲区属于直接内存缓冲区。

当 Historical 节点处理查询时,它必须打开一组段(segments)进行读取。这同样需要一些直接内存空间,详见 段解压缓冲区

以下是估算直接内存使用量的公式:

(druid.processing.numThreads + druid.processing.numMergeBuffers + 1) * druid.processing.buffer.sizeBytes

+ 1 这个因子是一个模糊估算,旨在计入段解压缓冲区。

连接池大小调整

请参阅 连接池通用指南 一节,了解连接池配置的概述。

对于 Historical 节点,druid.server.http.numThreads 应设置为略高于集群中所有 Broker 节点的 druid.broker.http.numConnections 总和的值。

将集群调优为每个 Historical 节点可以接受 50 个查询和 10 个非查询请求,是一个合理的起点。

段缓存大小

为了获得更好的查询性能,分配给 Historical 节点的数据段总量不应超过系统空闲内存。Historical 节点使用空闲系统内存来缓存数据段。更多详情,请参阅 从缓存中加载和提供数据段

Druid 使用 druid.segmentCache.locations 来计算分配给 Historical 节点的段数据总大小。对于极少数用例,您可以通过 druid.server.maxSize 属性覆盖此行为。

Historical 节点数量

集群中所需的 Historical 节点数量取决于集群拥有的数据量。为了获得良好的性能,您需要足够的 Historical 节点,以使每个 Historical 节点都有良好的 (空闲系统内存 / druid.segmentCache.locations 总大小) 比例,如上述段缓存大小部分所述。

只要能满足您用例的容错要求,拥有较少的大型服务器通常优于拥有大量小型服务器。

SSD 存储

我们建议在 Historical 节点上使用 SSD 存储,因为它们需要处理存储在磁盘上的段数据。

总内存使用量

根据这些指南估算 Historical 节点的总内存使用量:

  • 堆内存:(0.5GiB * CPU 核心数) + (2 * 查找映射总大小) + druid.cache.sizeInBytes
  • 直接内存:(druid.processing.numThreads + druid.processing.numMergeBuffers + 1) * druid.processing.buffer.sizeBytes

Historical 节点会将任何可用的空闲系统内存(即 Historical JVM 堆/直接内存缓冲区或其他系统进程未使用的内存)用于磁盘上段的内存映射。为了获得更好的查询性能,请确保良好的 (空闲系统内存 / druid.segmentCache.locations 总大小) 比例,以便将更大比例的段保留在内存中。

段大小的重要性

请务必查看 段大小优化 以帮助调优您的 Historical 进程,从而实现最高性能。

Broker

堆大小调整

Broker 节点堆内存消耗的主要来源是:

  • 来自 Historical 节点和任务的部分未合并查询结果。
  • 段时间线:这包含当前 可用 的所有段的位置信息(哪个 Historical/Task 正在服务该段)。
  • 缓存的段元数据:这包含所有当前可用段的元数据,例如每个段的模式(schema)。

Broker 的堆需求随着集群中段的数量和段的总数据大小而扩展。

堆大小会根据数据大小和使用模式而变化,但 4GiB 到 8GiB 是小型或中型集群(约 15 台服务器或以下)的一个很好的起点。作为高端内存需求的大致估计,约 100 个节点规模的超大型集群可能需要 30GiB-60GiB 的 Broker 堆。

如果 Broker 上启用了缓存,缓存将存储在堆中,大小由 druid.cache.sizeInBytes 设定。

直接内存大小调整

在 Broker 上,所需的直接内存量取决于配置了多少合并缓冲区(用于合并 GroupBy)。Broker 通常不需要处理线程或处理缓冲区,因为查询结果是在 HTTP 连接线程中堆内(on-heap)合并的。

  • druid.processing.buffer.sizeBytes 可以设置为 500MiB。
  • druid.processing.numMergeBuffers:将其设置为与 Historical 节点相同的值或稍高一点。

连接池大小调整

请参阅 连接池通用指南 一节,了解连接池配置的概述。

在 Broker 上,请确保所有 Broker 的 druid.broker.http.numConnections 之和略低于您的 Historical 节点和 Task 的 druid.server.http.numThreads 值。

Broker 上的 druid.server.http.numThreads 应设置为略高于同一 Broker 上的 druid.broker.http.numConnections 的值。

将集群调优为每个 Historical 节点可以接受 50 个查询和 10 个非查询请求,并相应调整 Broker,是一个合理的起点。

Broker 反压

当从 Historical 进程或 Task 检索查询结果时,Broker 可以选择指定缓冲区的最大大小来存放排队、未读取的数据,并在达到限制时对 Historical 或 Task 的通道施加反压(导致 Historical/Task 侧的通道写入被阻塞,直到 Broker 从通道中消耗掉一些数据)。

此缓冲区大小由 druid.broker.http.maxQueuedBytes 设置控制。

该限制会被平摊到查询所触及的 Historicals/Tasks 数量上:假设我将 druid.broker.http.maxQueuedBytes 设置为 5MiB,且 Broker 收到的查询需要扇出到 2 个 Historical 节点。在这种情况下,每个 Historical 通道将获得 2.5MiB 的缓冲区。

通常可以将其设置为大约 2MiB * Historical 节点数量 的值。随着集群规模扩大,Historical 节点和 Task 增多,请考虑相应增加此缓冲区大小并相应增加 Broker 堆。

  • 如果缓冲区太小,会导致缓冲区迅速填满并阻塞通道,从而导致查询效率低下。
  • 如果缓冲区太大,由于 HTTP 通道中排队的查询结果数据更多,会给 Broker 带来更大的内存压力。

Broker 数量

Broker 与 Historical 节点的 1:15 比例是一个合理的起点(这并非硬性规定)。

如果您需要 Broker 高可用性(HA),最初可以部署 2 个,然后使用 1:15 的比例指南来增加额外的 Broker。

总内存使用量

根据这些指南估算 Broker 的总内存使用量:

  • 堆内存:分配的堆大小
  • 直接内存:(druid.processing.numMergeBuffers + 1) * druid.processing.buffer.sizeBytes

Middle Manager

Middle Manager 是一个轻量级的任务控制器/管理器,负责启动执行摄入工作的 Task 进程。

Middle Manager 堆大小调整

Middle Manager 本身不需要太多资源,通常可以将堆设置为约 128MiB。

SSD 存储

我们建议在 Middle Manager 上使用 SSD 存储,因为 Middle Manager 启动的任务需要处理存储在磁盘上的段数据。

任务数量

Middle Manager 可以启动的任务数量由 druid.worker.capacity 设置控制。

集群中所需的工作节点(workers)数量取决于您的用例需要同时运行多少个摄入任务。在给定机器上可以启动的工作节点数量取决于为每个工作节点分配的资源量以及可用的系统资源。

您可以向集群添加更多的 Middle Manager 机器来增加任务容量。

任务配置

以下部分介绍了 Middle Manager 启动的任务的配置。这些任务既可以被查询又可以执行摄入工作负载,因此它们比 Middle Manager 需要更多的资源。

任务堆大小调整

1GiB 的堆通常足以满足任务需求。

查找(Lookups)

如果您正在使用查找功能,请计算所加载查找映射的总大小。

Druid 在更新查找映射时执行原子交换(交换期间旧映射和新映射将同时存在于堆中),因此查找映射产生的最大潜在堆内存使用量为 (2 * 所有加载查找的总大小)。

如果您正在使用查找功能,请务必在任务堆大小中加上 (2 * 所有加载查找的总大小)

任务处理线程与缓冲区

对于任务,通常 1 或 2 个处理线程就足够了,因为任务倾向于持有比 Historical 进程少得多的可查询数据。

  • druid.indexer.fork.property.druid.processing.numThreads:设置为 1 或 2
  • druid.indexer.fork.property.druid.processing.numMergeBuffers:设置为 2
  • druid.indexer.fork.property.druid.processing.buffer.sizeBytes:可以设置为 100MiB
直接内存大小调整

上述的处理缓冲区和合并缓冲区属于直接内存缓冲区。

当任务处理查询时,它必须打开一组段进行读取。这也需要一些直接内存空间,详见 段解压缓冲区

摄入任务还需要合并部分摄入结果,这需要直接内存空间,详见 段合并

以下是估算直接内存使用量的公式:

(druid.processing.numThreads + druid.processing.numMergeBuffers + 1) * druid.processing.buffer.sizeBytes

+ 1 这个因子是一个模糊估算,旨在计入段解压缓冲区和字典合并缓冲区。

连接池大小调整

请参阅 连接池通用指南 一节,了解连接池配置的概述。

对于任务,druid.server.http.numThreads 应设置为略高于集群中所有 Broker 节点的 druid.broker.http.numConnections 总和的值。

将集群调优为每个任务可以接受 50 个查询和 10 个非查询请求,是一个合理的起点。

总内存使用量

根据这些指南估算任务的总内存使用量:

  • 堆内存:1GiB + (2 * 查找映射总大小)
  • 直接内存:(druid.processing.numThreads + druid.processing.numMergeBuffers + 1) * druid.processing.buffer.sizeBytes

Middle Manager + 任务的总内存使用量:

MM 堆大小 + druid.worker.capacity * (单个任务内存使用量)

特定摄入类型的配置指南
Kafka/Kinesis 摄入

如果您使用 Kafka 索引服务Kinesis 索引服务,所需的任务数量将取决于分区数和您的 taskCount/副本设置。

除了这些要求外,在集群中分配更多的任务槽是一个好主意,这样您可以有空闲的任务槽用于其他任务,例如 压缩任务

并行原生摄入

如果您正在使用 并行原生批处理摄入,分配更多的可用任务槽是个好主意,这将允许更高的摄入并发性。

Coordinator

Coordinator 节点上性能相关的核心设置是堆大小。

Coordinator 的堆需求随集群中服务器、段和任务的数量而扩展。

您可以将 Coordinator 的堆设置为与 Broker 堆相同的大小,或略小一点:这两个服务都需要处理集群范围的状态并回答有关该状态的 API 请求。

动态配置

percentOfSegmentsToConsiderPerMove

  • 默认值为 100。这意味着当 Coordinator 寻找要移动的段时,它会考虑所有段。Coordinator 会做出加权选择,容量最少的服务器上的段被移动的可能性最大。
    • 这种加权选择策略意味着可用容量最大的服务器上的段最不容易被选中。
    • 随着集群中段数量的增加,选择第 N 个段进行移动的概率会降低;其中 N 是最后考虑移动的段。
    • 管理员可以使用此配置跳过对该第 N 个段的考虑。
  • 我们不是跳过特定数量的段,而是跳过集群中一定百分比的段。
    • 例如,将该值设置为 25 时,只有前 25% 的段才会被视为可以移动的段。这 25% 的段将来自可用容量最少的服务器。
      • 在此示例中,Coordinator 每次寻找要移动的段时,考虑的段数量将比配置为 100 时减少 75%。在拥有数十万个段的集群上,这可以节省大量的时间。
  • 此配置的一般建议:
    • 如果您不担心 Coordinator 完成完整协调周期所需的时间,则通常不需要修改此配置。
    • 如果您对 Coordinator 运行完整协调周期所需的时间感到不满,并且您已将 Coordinator 动态配置 maxSegmentsToMove 设置为大于 0 的值(默认值为 5),将此配置设置为非默认值有助于缩短协调时间。
      • 推荐的起点值为 66。它代表了所考虑段百分比的有意义的减少,同时也不会过于激进(使用此值,每次移动操作将减少 1/3 的段考虑)。
  • 修改此配置对协调时间的影响,将取决于您将配置值设置得有多低、maxSegmentsToMove 的值以及集群中的段总数。
    • 如果您的集群拥有的段数量相对较少,或者您选择在每个协调周期内移动的段很少,那么此处可能节省的空间并不大。

Overlord

Overlord 节点上性能相关的核心设置是堆大小。

Overlord 的堆需求主要随运行中的任务数量而扩展。

Overlord 通常比 Coordinator 或 Broker 需要更少的资源。通常可以将 Overlord 堆设置为 Coordinator 堆的 25-50%。

Router

Router 节点的资源需求较低,因为它将请求代理给 Broker,而自身不需要执行太多的计算工作。

作为起点,您可以分配 256MiB 的堆,并在需要时增加它。

处理线程与缓冲区的指南

处理线程

druid.processing.numThreads 配置控制用于计算查询结果的处理线程池的大小。此池的大小限制了可以同时处理的查询数量。

处理缓冲区

druid.processing.buffer.sizeBytes 是一个密切相关的属性,它控制分配给处理线程的堆外缓冲区大小。

每个处理线程分配一个缓冲区。对于一般用途,500MiB 到 1GiB 之间的大小是一个合理的选择。

TopN 和 GroupBy 查询使用这些缓冲区来存储中间计算结果。随着缓冲区大小的增加,单次传递可以处理更多的数据。

GroupBy 合并缓冲区

如果您计划执行 GroupBy 查询,druid.processing.numMergeBuffers 是一个重要的配置属性。

GroupBy 查询使用额外的堆外缓冲区池来合并查询结果。这些缓冲区的大小与上述处理缓冲区相同,由 druid.processing.buffer.sizeBytes 属性设置。

非嵌套 GroupBy 查询每个查询需要 1 个合并缓冲区,而嵌套 GroupBy 查询需要 2 个合并缓冲区(无论嵌套深度如何)。

合并缓冲区的数量决定了可以并发处理的 GroupBy 查询数量。

利用指标优化 GroupBy 缓冲区配置

Druid 可以发出指标,帮助您正确调整合并缓冲区和相关的 GroupBy 配置。通过将 org.apache.druid.server.metrics.GroupByStatsMonitor 添加到 druid.monitoring.monitors 来启用 GroupByStatsMonitor 模块后,即可获得这些指标。详细信息请参阅 指标参考

调整 druid.processing.buffer.sizeBytes
  • mergeBuffer/maxBytesUsed:在发射周期内,任何单个 GroupBy 查询使用的峰值合并缓冲区字节数。如果该值始终接近 druid.processing.buffer.sizeBytes,请考虑增加缓冲区大小。
  • groupBy/maxSpilledBytes:任何单个 GroupBy 查询溢出到磁盘的峰值字节数。非零值表示合并缓冲区太小,无法在内存中容纳中间结果,导致磁盘溢出。增加 druid.processing.buffer.sizeBytes 可以减少溢出。您还可以调整 druid.query.groupBy.maxOnDiskStorage 来控制在查询失败前允许多少溢出。
  • groupBy/spilledQueries:在发射周期内溢出到磁盘的 GroupBy 查询数量。非零值可能表明您的缓冲区大小太小,应该增加以避免因过度溢出导致的性能问题。
调整 druid.processing.numMergeBuffers
  • mergeBuffer/pendingRequests:等待获取合并缓冲区的查询数量。持续的非零值表示合并缓冲区池耗尽;请考虑增加 druid.processing.numMergeBuffers
  • mergeBuffer/maxAcquisitionTimeNs:任何单个 GroupBy 查询等待获取合并缓冲区的峰值时间(纳秒)。高值表明合并缓冲区池存在争用;增加 druid.processing.numMergeBuffers 可以减少等待时间。
调整 druid.query.groupBy.maxMergingDictionarySize
  • groupBy/maxMergeDictionarySize:任何单个 GroupBy 查询的堆内峰值合并字典大小(字节)。如果接近 druid.query.groupBy.maxMergingDictionarySize,则查询可能会溢出到磁盘(如果已配置 druid.query.groupBy.maxOnDiskStorage)或失败。如果发生这种情况,请考虑增加字典大小限制。

连接池指南

每个 Druid 进程都有一个用于 HTTP 连接处理线程数的配置属性:druid.server.http.numThreads

HTTP 服务器线程数限制了给定进程可以处理的并发 HTTP API 请求数量。

为查询连接池调整大小

Broker 有一个设置 druid.broker.http.numConnections,用于控制它可以向给定的 Historical 或 Task 进程发出的外向连接数量。

这些连接用于将查询发送到 Historicals 或 Tasks,每个查询占用一个连接;druid.broker.http.numConnections 的值实际上限制了给定 Broker 可以并发处理的查询数量。

假设我们有一个包含 3 个 Broker 的集群,且 druid.broker.http.numConnections 设置为 10。

这意味着集群中的每个 Broker 将向每个单独的 Historical 或 Task 打开最多 10 个连接(每个 Historical/Task 总共有 30 个入站查询连接)。

在 Historical/Task 侧,这意味着 druid.server.http.numThreads 必须设置为至少与集群中所有 Broker 的 druid.broker.http.numConnections 总和一样大的值。

实际上,您需要为非查询 API 请求(例如状态检查)分配额外的服务器线程;通常添加 10 个线程是一个不错的准则。使用包含 3 个 Broker 的集群示例,且 druid.broker.http.numConnections 设置为 10,则 Historicals 和 Tasks 的 druid.server.http.numThreads 设置为 40 会比较合适。

作为起点,Historicals 和 Tasks 允许 50 个并发查询(读取数据源段数据的请求)+ 10 个非查询请求(状态检查等其他请求)是合理的(即在那里将 druid.server.http.numThreads 设置为 60),同时根据集群中的 Broker 数量调整 druid.broker.http.numConnections,以使其符合每个 Historical/Task 50 个查询连接的限制。

  • 如果 Broker 和 Historicals/Tasks 之间的连接池太小,集群将得不到充分利用,因为并发查询槽太少。
  • 如果连接池太大,您可能会因为过度的并发负载而遇到内存不足错误,并增加资源争用。
  • 连接池大小调整在您需要 QoS 类型保证并使用查询优先级时最为重要;否则,这些设置可以更宽松地配置。
  • 如果您的集群使用模式倾向于大量的短小并发查询(每个查询耗时少于约 15 毫秒),扩大连接池是个好主意。
  • 这里的 50/10 通用指南是一个粗略的起点,因为不同的查询对系统施加的负载量不同。为了更精确地为您的集群调整连接池大小,您需要了解查询的执行时间,并确保传入查询的速率不超过您的“排水”速率。

段内直接内存缓冲区

段解压

在段合并或查询处理期间打开段进行读取时,Druid 会为读取的每一列分配一个 64KiB 的堆外解压缓冲区。

因此,在读取段时,会有 (64KiB * 每段读取的列数 * 读取的段数) 的额外直接内存开销。

段合并

除了上述段解压开销外,当在摄入期间合并一组段时,会为该合并集合中的每个段的每个 String 类型列分配一个直接缓冲区。

这些缓冲区的大小等于该列在其段内的基数(cardinality)乘以 4 字节(缓冲区存储整数)。

例如,如果正在合并两个段,第一个段有一个基数为 1000 的 String 列,第二个段有一个基数为 500 的 String 列,合并步骤将分配 (1000 + 500) * 4 = 6000 字节的直接内存。

这些缓冲区用于跨段合并 String 列的值字典。这些“字典合并缓冲区”独立于 druid.processing.numMergeBuffers 配置的“合并缓冲区”。

一般建议

JVM 调优

垃圾回收

我们建议使用 G1GC 垃圾回收器:

-XX:+UseG1GC

启用内存溢出时进程终止也是有用的,因为进程通常无法从这种状态恢复,最好重启进程。

-XX:+ExitOnOutOfMemoryError

其他通用的实用 JVM 参数

-Duser.timezone=UTC
-Dfile.encoding=UTF-8
-Djava.io.tmpdir=<should not be volatile tmpfs and also has good read and write speed. Strongly recommended to avoid using NFS mount>
-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
-Dorg.jboss.logging.provider=slf4j
-Dnet.spy.log.LoggerImpl=net.spy.memcached.compat.log.SLF4JLogger
-Dlog4j.shutdownCallbackRegistry=org.apache.druid.common.config.Log4jShutdown
-Dlog4j.shutdownHookEnabled=true
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintGCTimeStamps
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintGCApplicationConcurrentTime
-Xloggc:/var/logs/druid/historical.gc.log
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=50
-XX:GCLogFileSize=10m
-XX:+ExitOnOutOfMemoryError
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/var/logs/druid/historical.hprof
-XX:MaxDirectMemorySize=1g
信息

请注意,上述参数设置仅代表通用的指导样本。请务必谨慎使用适合您特定场景的值,并在暂存环境中测试任何更改。

ExitOnOutOfMemoryError 参数仅从 JDK 8u92 开始支持。对于旧版本,可以使用 -XX:OnOutOfMemoryError='kill -9 %p'

MaxDirectMemorySize 限制了 JVM 分配的直接内存上限,设置为不限制则移除了 JVM 限制,操作系统级别的内存限制仍然有效。确保 Druid 配置的堆外内存分配不超过机器可用内存仍然很重要。此处的重要设置包括 druid.processing.numThreadsdruid.processing.numMergeBuffersdruid.processing.buffer.sizeBytes

此外,对于较大的 JVM 堆,以下是一些已知的在某些情况下有助于提高垃圾回收效率的指南:

使用 UTC 时区

我们建议在所有事件以及所有主机上使用 UTC 时区,不仅是 Druid,而是整个数据基础设施。这可以大大减轻因时区不一致导致的潜在查询问题。要在非 UTC 时区查询,请参阅 查询粒度

系统配置

SSD

如果您运行的集群不是完全在内存中的,强烈建议为 Historical、Middle Manager 和 Indexer 进程使用 SSD。SSD 可以大大减轻将数据换入换出内存所需的时间。

JBOD 与 RAID

Historical 进程在磁盘上存储大量段,并支持指定多个存储路径。通常主机配置了 RAID,使它们对 OS 表现为单一磁盘。RAID 可能有开销,特别是如果是基于软件而非硬件控制器的。因此,Historical 节点在 JBOD 架构下可能获得更好的磁盘吞吐量。

交换空间(Swap space)

我们建议不要对 Historical、Middle Manager 和 Indexer 进程使用交换空间,因为大量内存映射的段文件可能导致性能低下且不可预测。

Linux 限制

对于 Historical、Middle Manager 和 Indexer 进程(以及超大规模集群的 Broker 进程),您可能需要调整某些 Linux 系统限制,以计入大量打开的文件、大量的网络连接或大量的内存映射文件。

ulimit

可以通过编辑 /etc/security/limits.conf 永久设置打开文件的限制。此值应显著大于服务器上存在的段文件数量。

max_map_count

Historical 进程(较小程度上还包括 Middle Manager 和 Indexer 进程)会对段文件进行内存映射,因此根据每个服务器的段数量,可能还需要调整 /proc/sys/vm/max_map_count。根据 Linux 发行版的不同,这可以通过 sysctl/etc/sysctl.d/ 中放置一个设置 vm.max_map_count 的文件来完成。