bigywater.tech
Elasticsearch · 108

Indexing Pressure

真实查到indexing_pressure内存上限精确等于堆大小的10%,用6个约29.4MB的并发大bulk请求真实触发按内存字节数记账的拒绝机制,验证它跟上一篇验证的线程池队列拒绝是独立运作的两套互补保护机制。

indexing_pressure内存上限
真实107374182字节,精确等于1GB堆的10%
6个约29.4MB并发大请求
真实只有3个成功,3个被拒绝
拒绝错误信息
真实精确嵌着内存记账数字证明按字节数限制

做的事:真实查看indexing_pressure这个内存保护机制的上限,以及是怎么算出来的

代码GET /_nodes/stats/indexing_pressure

验证:indexing_pressure的内存上限真实是107374182字节,精确等于本机ES堆大小1GB的10%

实测 · 本机 Elasticsearch 8.15.0 执行输出
limit_in_bytes: 107374182
  ← 本机ES_JAVA_OPTS设的是-Xmx1g,1073741824字节的10%精确就是107374182.4

这个真实数字验证了indexing_pressure默认上限的真实计算方式:它真实按JVM堆大小的固定比例(默认10%)划定一块"写入相关内存占用"的预算,一旦正在处理中的写入请求(包括协调节点阶段收到的原始请求体、以及在主分片/副本分片上处理这些请求占用的内存)累计超过这个预算,ES真实就会开始拒绝新的写入,防止写入压力真的把JVM堆内存耗尽导致OOM。

真实构造6个约29.4MB的大bulk请求,同时并发发出,看会不会真实触发这个内存保护

代码真实构造一个包含15000条文档、约29.4MB大小的bulk请求体 真实用6个线程同时把这同一份29.4MB请求体发往_bulk接口(真实总请求量约176MB,远超107MB上限)

验证:6个并发大请求真实只有3个成功,3个真实被拒绝,错误信息里精确嵌着真实的内存记账数字

实测 · 本机执行输出
{'success': 3, 'rejected_pressure': 3}

真实其中一条拒绝的错误信息:
→ "rejected execution of coordinating operation
   [coordinating_and_primary_bytes=97886910, replica_bytes=0,
    all_bytes=97886910, coordinating_operation_bytes=32628970,
    max_coordinating_and_primary_bytes=107374182]"

真实的indexing_pressure统计: coordinating_rejections=3
这条真实报错把内存记账过程摊开得一清二楚:在这次被拒绝的请求到达时,节点上真实已经有97886910字节(约93.3MB)的写入请求正在处理中(coordinating_and_primary_bytes),这次新请求真实估算需要再占用32628970字节(约31.1MB,真实的请求体序列化之后在内存里的占用通常会比原始JSON文本体积更大),两者加起来真实超过了107374182这个上限,所以真实在请求还没真正开始处理之前就被拦截拒绝了。这正是indexing_pressure区别于本系列上一篇验证过的write线程池拒绝的真实本质:线程池拒绝真实按"有多少个请求在排队"这个数量维度做限制,indexing_pressure真实按"这些请求加起来真实占用了多少字节内存"这个体量维度做限制——哪怕线程池队列还有空位,只要真实堆积的写入请求总体量超过了内存预算,依然会真实被拒绝。两套机制真实独立运作、互不替代,共同构成了ES应对写入过载的双重保护网:数量维度防止队列无限堆积,内存维度防止少量但是巨大的请求把堆内存直接撑爆。

分步演示:Indexing Pressure从真实的内存上限计算到并发大请求触发拒绝的完整验证

每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。

indexing_pressure按内存字节数限制写入压力,独立于按数量限制的线程池队列
这一步新验证的内存压力状态

    本文用到的工具

    • 本机真实部署的 Elasticsearch 8.15.0(单节点,tar包直接启动)
    • 真实的 _nodes/stats/indexing_pressure API
    京ICP备2026067502号-1京公网安备11010502063487号