Troubleshooting

Tuning JVM Heap Memory Elasticsearch

Elasticsearch berjalan di atas JVM, dan ukuran heap yang salah adalah penyebab umum OutOfMemoryError, garbage collection panjang, dan node tidak responsif. Panduan ini membahas aturan ukuran heap, cara menyetelnya, gejala masalah, diagnosis, serta circuit breaker dan field data.

Dua Aturan Emas Heap

≤ 50% RAM fisik

Sisakan setengah RAM untuk filesystem cache OS. Lucene sangat bergantung padanya untuk kecepatan baca. Heap terlalu besar justru memperlambat.

≤ ~31GB

Di bawah ~32GB, JVM memakai compressed oops (pointer 32-bit). Melewatinya, heap 40GB menampung lebih sedikit objek daripada 31GB.

RAM serverHeap disarankanCatatan
8 GB4 GB50% RAM.
16 GB8 GB50% RAM.
32 GB16 GB50% RAM.
64 GB31 GBDibatasi ambang compressed oops, bukan 50%.
128 GB31 GB + node keduaJalankan beberapa node 31GB per mesin.

Cara Menyetel Heap

Selalu setel Xms (min) sama dengan Xmx (max) agar JVM tidak perlu mengubah ukuran heap saat runtime.

Opsi A — jvm.options.d (disarankan)

# config/jvm.options.d/heap.options
-Xms16g
-Xmx16g

Opsi B — variabel lingkungan

# mis. di docker / systemd
ES_JAVA_OPTS="-Xms16g -Xmx16g"
Jangan mengedit langsung file jvm.options bawaan saat upgrade akan menimpanya. Pakai folder jvm.options.d/ agar setelan Anda bertahan antar versi.
Verifikasi heap aktif: GET /_nodes/jvm?filter_path=**.mem.heap_max atau lihat heap.max di _cat/nodes.

Gejala OOM & GC Panjang

# GC muda yang lama & sering di log
[gc][young][1432][88] duration [2.4s], collections [1]/[3.1s],
  total [2.4s]/[1.2m], memory [15.2gb]->[14.9gb]/[16gb]

# circuit breaker tersandung
{ "type": "circuit_breaking_exception",
  "reason": "[parent] Data too large, data for [<http_request>]
    would be larger than limit" }

# puncaknya: node mati
java.lang.OutOfMemoryError: Java heap space
GC yang sering memakan >1 detik dan heap yang tak pernah turun di bawah ~75% setelah old GC adalah tanda kuat heap kurang atau ada query/aggregasi boros memori.

Diagnosis

# pemakaian heap ringkas per node
GET /_cat/nodes?v&h=name,heap.percent,heap.current,heap.max,ram.percent,cpu,load_1m
name  heap.percent heap.current heap.max ram.percent cpu load_1m
es-01           91       14.6gb     16gb          78  64    3.10
es-02           63       10.1gb     16gb          71  22    1.40
# statistik JVM rinci: heap, GC, pool
GET /_nodes/stats/jvm?filter_path=nodes.*.jvm.mem,nodes.*.jvm.gc
# status semua circuit breaker
GET /_nodes/stats/breaker?filter_path=nodes.*.breakers
IndikatorSehatBermasalah
heap.percent< 75% rata-rataKonsisten > 85%
Durasi old GC< 1 detik, jarang> 1 detik, sering
breakers.parent.tripped0Naik terus

Circuit Breaker & Field Data

Circuit breaker menolak operasi yang diperkirakan menghabiskan memori, mencegah OOM yang mematikan node. Field data adalah struktur in-heap untuk agregasi/sort pada field text — sering jadi biang pemborosan heap.

# batas circuit breaker (dynamic)
PUT /_cluster/settings
{
  "persistent": {
    "indices.breaker.total.limit": "70%",
    "indices.breaker.fielddata.limit": "40%"
  }
}
Jangan agregasi/sort pada field text langsung — itu mengaktifkan field data yang boros heap. Pakai multi-field .keyword yang memakai doc values di disk, bukan heap.
# benar: agregasi pakai sub-field keyword (doc values, hemat heap)
GET /produk/_search
{ "aggs": { "merek": { "terms": { "field": "merek.keyword" } } } }

Tips & Kesimpulan

  • Setel Xms = Xmx, maksimal 50% RAM, tidak lebih dari ~31GB.
  • RAM besar > 64GB lebih baik dijadikan beberapa node 31GB daripada satu heap raksasa.
  • Hindari agregasi/sort pada field text; pakai sub-field keyword berbasis doc values.
  • Pantau heap.percent dan durasi GC; pasang alert pada heap > 85% berkelanjutan.
  • Kurangi shard berlebih — tiap shard memakai overhead heap; gabungkan shard kecil yang banyak.

FAQ Tuning JVM Heap

Berapa ukuran heap JVM yang ideal untuk Elasticsearch?

Aturannya: heap maksimal 50% dari RAM fisik, dan jangan melebihi sekitar 31GB. Sisa RAM dibiarkan untuk filesystem cache OS yang dipakai Lucene. Melewati ~31-32GB membuat JVM kehilangan compressed ordinary object pointers (compressed oops), sehingga heap besar justru kurang efisien.

Kenapa heap tidak boleh lebih dari 31GB?

Di bawah ambang ~32GB, JVM memakai compressed oops yang menyimpan pointer objek dalam 32-bit, menghemat memori dan mempercepat akses. Di atas ambang itu pointer menjadi 64-bit penuh, sehingga heap 40GB bisa menampung objek lebih sedikit daripada heap 31GB. Karena itu 31GB adalah batas praktis.

Apa gejala heap kekurangan memori?

Gejalanya: GC (garbage collection) lama dan sering muncul di log (mis. "[gc][young] ... collections ... took [Xs]"), heap.percent konsisten tinggi (di atas 85%), node lambat atau tidak responsif, dan akhirnya OutOfMemoryError yang bisa membuat node mati. Circuit breaker juga mulai menolak request.

Apa fungsi circuit breaker pada Elasticsearch?

Circuit breaker mencegah operasi yang akan memakai memori berlebih sehingga menghindari OutOfMemoryError yang mematikan node. Bila estimasi pemakaian melewati batas, request ditolak dengan circuit_breaking_exception. Ini melindungi stabilitas node dengan mengorbankan satu request, bukan seluruh node.

Hitung shard ideal untuk hemat heap

Terlalu banyak shard kecil membebani heap. Gunakan kalkulator shard untuk menentukan jumlah yang sehat.

Buka Kalkulator Shard