快取及使用 Circuit Breaker 限制記憶體使用

CrazyZard發表於2020-03-09
  • Elasticsearch 的快取主要分成三大類
    • Node Query Cache (Filter Context)
    • Shard Query Cache (Cache Query的結果)
    • Fielddata Cache

快取及使用 Circuit Breaker 限制記憶體使用

  • 每一個節點有一個 Node Query 快取
    • 由該節點的所有 Shard 共享,只快取 Filter Context 相關內容
    • Cache 採用 LRU 演算法
  • 靜態配置,需要設定在每個 Data Node 上
    • Node Level - indices.queries.cache.size: ”10%” - Index Level: index.queries.cache.enabled: true
  • 快取每個分片上的查詢結果
    • 只會快取設定了 size=0 的查詢對應的結果。不會快取 hits。但是會快取 Aggregations 和 Suggestions
  • Cache Key
    • LRU 演算法,將整個 JSON 查詢串作為 Key,與 JSON 對 象的順序相關
  • 靜態配置
    • 資料節點:indices.requests.cache.size: “1%”

快取及使用 Circuit Breaker 限制記憶體使用

  • 除了 Text 型別,預設都採用 doc_values。節約了記憶體
    • Aggregation 的 Global ordinals 也儲存在 Fielddata cache 中
  • Text 型別的欄位需要開啟 Fileddata 才能對其進行聚合和排序
    • Text 經過分詞,排序和聚合效果不佳,建議不要輕易使用
  • 配置
    • 可以控制 Indices.fielddata.cache.size, 避免產生 GC (預設無限制)
  • Node Query Cache
    • 儲存的是 Segment 級快取命中的結果。Segment 被合併後,快取會失效
  • Shard Request Cache
    • 分片 Refresh 時候,Shard Request Cache 會失效。如果 Shard 對應的資料頻繁發生變化,該快取的效 率會很差
  • Fielddata Cache
    • Segment 被合併後,會失效
  • Elasticsearch 高效運維依賴於記憶體的合理分配
    • 可用記憶體一半分配給 JVM,一半留給作業系統,快取索引檔案
  • 記憶體問題,引發的問題
    • 長時間 GC,影響節點,導致叢集響應緩慢
    • OOM, 導致丟節點
  • 檢視各個節點的記憶體狀況
    • GET _cat/nodes?v
    • GET _nodes/stats/indices?pretty
    • GET _cat/nodes?v&h=name,queryCacheMemory,queryCacheEvictions,requestCacheMemory,reques tCacheHitCount,request_cache.miss_count
    • GET _cat/nodes?h=name,port,segments.memory,segments.index_writer_memory,fielddata.memo ry_size,query_cache.memory_size,request_cache.memory_size&v
  • Segments 個數過多,導致 full GC

    • 現象:叢集整體響應緩慢,也沒有特別多的資料讀寫。但是發現節點在持續進行 Full G
    • 分析:檢視 Elasticsearch 的記憶體使用,發現 segments.memory 佔用很大空間
    • 解決:通過 force merge,把 segments 合併成一個
    • 建議:對於不在寫入和更新的索引,可以將其設定成只讀。同時,進行 force merge 操作。如 果問題依然存在,則需要考慮擴容。此外,對索引進行 force merge ,還可以減少對 global_ordinals 資料結構的構建,減少對 fielddata cache 的開銷
  • Field data cache 過大,導致 full GC

    • 現象:叢集整體響應緩慢,也沒有特別多的資料讀寫。但是發現節點在持續進行 Full GC
    • 分析:檢視 Elasticsearch 的記憶體使用,發現 fielddata.memory.size 佔用很大空間。同時,資料不存在寫入和更新,也執行過 segments merge。
    • 解決:將 indices.fielddata.cache.size 設小,重啟節點,堆記憶體恢復正常
    • 建議:Field data cache 的構建比較重,Elasticsearch 不會主動釋放,所以這個值應該設定的保守一些。如果業務上確實有所需要,可以通過增加節點,擴容解決
  • 複雜的巢狀聚合,導致叢集 full GC

    • 現象:節點響應緩慢,持續進行 Full GC
    • 分析:匯出 Dump 分析。發現記憶體中有大量 bucket 物件,檢視 日誌,發現複雜的巢狀聚合
    • 解決:優化聚合
    • 建議:在大量資料集上進行巢狀聚合查詢,需要很大的堆記憶體來完成。如果業務場景確實需要。 則需要增加硬體進行擴充套件。同時,為了避免這類查詢影響整個叢集,需要設定 Circuit Breaker 和 search.max_buckets 的數值
  • 包含多種斷路器,避免不合理操作引發的 OOM,每個斷路器可以指定記憶體使用的限制
    • Parent circuit breaker:設定所有的熔斷器可以使用的記憶體的總量
    • Fielddata circuit breaker:載入 fielddata 所需要的記憶體
    • Request circuit breaker:防止每個請求級資料結構超過一定的記憶體(例如聚合計算的記憶體)
    • In flight circuit breaker:Request中的斷路器
    • Accounting request circuit breaker:請求結束後不能釋放的物件所佔用的記憶體
  • GET /_nodes/stats/breaker?
    • Tripped 大於 0, 說明有過熔斷
    • Limit size 與 estimated size 約接近,越可能引發熔斷
  • 千萬不要觸發了熔斷,就盲目調大引數,有可能會導致叢集出問 題,也不因該盲目調小,需要進行評估
  • 建議將叢集升級到 7.x,更好的 Circuit Breaker 實現機制
    • 增加了 indices.breaker.total.use_real_memory 配置項,可以更加精準的分析記憶體狀況,避免 OOM

快取及使用 Circuit Breaker 限制記憶體使用

https://www.elastic.co/blog/improving-node...

本作品採用《CC 協議》,轉載必須註明作者和本文連結

快樂就是解決一個又一個的問題!

相關文章