[ElasticSearch]生產環境集羣部署最佳實踐

在生產環境搭建或維護 Elasticsearch 集羣和個人搭建集羣的小打小鬧有非常大的不同。

本文的最佳實踐基於每天增量數億+ 的線上環境。

少囉嗦,上乾貨。

1、內存

Elasticsearch 和 Lucene 都是 Java 語言編寫,這意味着我們必須注意堆內存的設置。

Elasticsearch 可用的堆越多,它可用於過濾器(filter)和其他緩存的內存也就越多,更進一步講可以提高查詢性能。

但請注意,過多的堆可能會使垃圾回收暫停時間過長。請勿將堆內存的最大值設置爲 JVM 用於壓縮對象指針(壓縮的 oops)的臨界值之上,確切的臨界值有所不同,但不要超過 32 GB

推薦:乾貨 | 喫透Elasticsearch 堆內存

常見內存配置坑 1:堆內存設置過大

舉例:Elasticsearch 宿主機:64 GB 內存,堆內存恨不得設置爲 64 GB。

但,這忽略了堆的另一部分內存使用大戶:OS 文件緩存。

Lucene 旨在利用底層操作系統來緩存內存中的數據結構。Lucene 段存儲在單獨的文件中。

由於段是不可變的(immutable),因此這些文件永遠不會更改。這使它們非常易於緩存,並且底層操作系統很樂意將熱段駐留在內存中,以加快訪問速度。

這些段包括倒排索引(用於全文搜索)和doc values 正排索引(用於聚合)。Lucene 的性能取決於與 OS 文件緩存的交互。

如果你將所有可用內存分配給 Elasticsearch 的堆,則 OS 文件緩存將不會剩下任何可用空間。這會嚴重影響性能。

官方標準建議是:將 50% 的可用內存(不超過 32 GB,一般建議最大設置爲:31 GB)分配給 Elasticsearch 堆,而其餘 50% 留給 Lucene 緩存

可以通過以下方式配置 Elasticsearch 堆:

  • 方式一:堆內存配置文件 jvm.options

# Xms represents the initial size of total heap space
# Xmx represents the maximum size of total heap space
-Xms16g
-Xmx16g
  • 方式二:啓動參數設置

ES_JAVA_OPTS="-Xms10g -Xmx10g" ./bin/elasticsearch

2、CPU

運行復雜的緩存查詢、密集寫入數據都需要大量的CPU,因此選擇正確的查詢類型以及漸進的寫入策略至關重要。

一個節點使用多個線程池來管理內存消耗。與線程池關聯的隊列使待處理的請求得以保留(類似緩衝效果)而不是被丟棄。

由於 Elasticsearch會做動態分配,除非有非常具體的要求,否則不建議更改線程池和隊列大小。

線程池和隊列的設置,參見:

Elasticsearch 線程池和隊列問題,請先看這一篇

推薦閱讀:

https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-threadpool.html

3、分片數

分片是 Elasticsearch 在集羣內分發數據的單位。集羣發生故障再恢復平衡的速度取決於分片的大小、分片數量、網絡以及磁盤性能。

在 Elasticsearch 中,每個查詢在每個分片的單個線程中執行。但是,可以並行處理多個分片。針對同一分片的多個查詢和聚合也可以並行處理。

這意味着在不涉及緩存的情況下,最小查詢延遲將取決於數據、查詢類型以及分片的大小三個因素。

3.1 設置很多小分片 VS 設置很少大分片?

  • 查詢很多小分片,導致每個分片能做到快速響應,但是由於需要按順序排隊和處理結果彙集。因此不一定比查詢少量的大分片快。

  • 如果存在多個併發查詢,那麼擁有大量小分片也會降低查詢吞吐量。

所以,就有了下面的分片數如何設定的問題?

3.2 分片數設定

選擇正確數量的分片是一個複雜問題,因爲在集羣規劃階段以及在數據寫入開始之前,一般不能確切知道文檔數。

對於集羣而言,分片數多了以後,索引和分片管理可能會使主節點超載,並可能會導致集羣無響應,甚至導致集羣宕機。

建議:爲主節點(Master 節點)分配足夠的資源以應對分片數過多可能導致的問題。

必須強調的是:主分片數是在索引創建時定義的,不支持藉助 update API 實現類副本數更新的動態修改。創建索引後,更改主分片數的唯一方法是重新創建索引,然後將原來索引數據 reindex 到新索引。

官方給出的合理的建議:每個分片數據大小:30GB-50GB

推薦1:Elasticsearch究竟要設置多少分片數?

https://elastic.blog.csdn.net/article/details/78080602

推薦2:Elasticsearch之如何合理分配索引分片

https://qbox.io/blog/optimizing-elasticsearch-how-many-shards-per-index

4、副本

Elasticsearch 通過副本實現集羣的高可用性,數據在數據節點之間複製,以實現主分片數據的備份,因此即便部分節點因異常下線也不會導致數據丟失。

默認情況下,副本數爲 1,但可以根據產品高可用要求將其增加。副本越多,數據的容災性越高。

副本多的另一個優點是,每個節點都擁有一個副本分片,有助於提升查詢性能。

銘毅提醒:

  • 實際副本數增多提高查詢性能建議結合集羣做下測試,我實測過效果不明顯

  • 副本數增多意味着磁盤存儲要加倍,也考驗硬盤空間和磁盤預算。

建議:根據業務實際綜合考慮設置副本數。普通業務場景(非精準高可用)副本設置爲 1 足夠了。

5、冷熱集羣架構配置

根據產品業務數據特定和需求,我們可以將數據分爲熱數據和冷數據,這是冷熱集羣架構的前提。

訪問頻率更高的索引可以分配更多更高配(如:SSD)的數據節點,而訪問頻率較低的索引可以分配低配(如:機械磁盤)數據節點。

冷熱集羣架構對於存儲諸如應用程序日誌或互聯網實時採集數據(基於時間序列數據)特別有用。

數據遷移策略:通過運行定時任務來實現定期將索引移動到不同類型的節點。

具體實現:curator 工具或藉助 ILM 索引生命週期管理。

5.1 熱節點

熱節點是一種特定類型的數據節點,關聯索引數據是:最近、最新、最熱數據。

因爲這些熱節點數據通常傾向於最頻繁地查詢。熱數據的操作會佔用大量 CPU 和 IO 資源,因此對應服務器需要功能強大(高配)並附加 SSD 存儲支持。

針對集羣規模大的場景,建議:至少運行 3 個熱節點以實現高可用性。

當然,這也和你實際業務寫入和查詢的數據量有關係,如果數據量非常大,可能會需要增加熱節點數目。

5.2 冷節點(或稱暖節點)

冷節點是對標熱節點的一種數據節點,旨在處理大量不太經常查詢的只讀索引數據。

由於這些索引是隻讀的,因此冷節點傾向於使用普通機械磁盤而非 SSD 磁盤。

與熱節點對標,也建議:最少 3 個冷節點以實現高可用性。

同樣需要注意的是,若集羣規模非常大,可能需要更多節點才能滿足性能要求。

甚至需要更多類型,如:熱節點、暖節點、冷節點等。

強調一下:CPU 和 內存的分配最終需要你通過使用與生產環境中類似的環境藉助 esrally 性能測試工具測試確定,而不是直接參考各種最佳實踐拍腦袋而定。

有關熱節點和熱節點的更多詳細信息,請參見:

https://www.elastic.co/blog/hot-warm-architecture-in-elasticsearch-5-x

推薦:冷熱集羣架構實戰

6、節點角色劃分

Elasticsearch 節點核心可分爲三類:主節點、數據節點、協調節點。

6.1 主節點

主節點:如果主節點是僅是候選主節點,不含數據節點角色,則它配置要求沒有那麼高,因爲它不存儲任何索引數據。

如前所述,如果分片非常多,建議主節點要提高硬件配置。

主節點職責:存儲集羣狀態信息、分片分配管理等。

同時注意,Elasticsearch 應該有多個候選主節點,以避免腦裂問題。

6.2 數據節點

數據節點職責:CURD、搜索以及聚合相關的操作。

這些操作一般都是IO、內存、CPU 密集型。

6.3 協調節點

協調節點職責:類似負載平衡器,主要工作是:將搜索任務分發到相關的數據節點,並收集所有結果,然後再將它們彙總並返回給客戶端應用程序。

6.4 節點配置參考

下表參見官方博客 PPT

角色 描述 存儲 內存 計算 網絡
數據節點 存儲和檢索數據 極高
主節點 管理集羣狀態
Ingest 節點 轉換輸入數據
機器學習節點 機器學習 極高 極高
協調節點 請求轉發和合並檢索結果

6.5 不同節點角色配置如下

必須配置到:elasticsearch.yml 中。

  • 主節點

node.master:true 
node.data:false 
  • 數據節點

node.master:false 
node.data:true 
  • 協調節點

node.master:false 
node.data:false

7、故障排除提示

Elasticsearch 的性能在很大程度上取決於宿主機資源情況。

CPU、內存使用率和磁盤 IO 是每個Elasticsearch節點的基本指標。

建議你在CPU使用率激增時查看Java虛擬機(JVM)指標。

7.1 堆內存使用率高

高堆內存使用率壓力以兩種方式影響集羣性能:

7.1.1 堆內存壓力上升到75%及更高

剩餘可用內存更少,並且集羣現在還需要花費一些 CPU 資源以通過垃圾回收來回收內存。

在啓用垃圾收集時,這些 CPU 週期不可用於處理用戶請求。結果,隨着系統變得越來越受資源約束,用戶請求的響應時間增加。

7.1.2 堆內存壓力繼續上升並達到接近100%

將使用更具侵略性的垃圾收集形式,這將反過來極大地影響集羣響應時間。

索引響應時間度量標準表明,高堆內存壓力會嚴重影響性能。

7.2 非堆內存使用率增長

JVM 外非堆內存的增長,吞噬了用於頁面緩存的內存,並可能導致內核級OOM。

7.3 監控磁盤IO

由於Elasticsearch大量使用存儲設備,磁盤 IO 的監視是所有其他優化的基礎,發現磁盤 IO 問題並對相關業務操作做調整可以避免潛在的問題。

應根據引起磁盤 IO 的情況評估對策,常見優化磁盤 IO 實戰策略如下:

  • 優化分片數量及其大小

  • 段合併策略優化

  • 更換普通磁盤爲SSD磁盤

  • 添加更多節點

7.5 合理設置預警

對於依賴搜索的應用程序,用戶體驗與搜索請求的等待時間長短相關。

有許多因素會影響查詢性能,例如:

  • 構造查詢方式不合理

  • Elasticsearch 集羣配置不合理

  • JVM 內存和垃圾回收問題

  • 磁盤 IO 等

查詢延遲是直接影響用戶體驗的指標,因此請確保在其上放置一些預警操作。

舉例:線上實戰問題:

圖片

如何避免?  以下兩個核心配置供參考:

PUT _cluster/settings
{
  "transient": {
    "search.default_search_timeout""50s",
    "search.allow_expensive_queries"false
  }
}

需要強調的是:"search.allow_expensive_queries"  是 7.7+ 版本纔有的功能,早期版本會報錯。

推薦閱讀:

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-wildcard-query.html

https://www.elastic.co/guide/en/elasticsearch/reference/current/search-your-data.html

7.6 合理配置緩存

默認情況下,Elasticsearch中的大多數過濾器都是高速緩存的。

這意味着在第一次執行過濾查詢時,Elasticsearch 將查找與過濾器匹配的文檔,並使用該信息構建名爲“bitset”的結構。

存儲在 bitset 中的數據包含文檔標識符以及給定文檔是否與過濾器匹配。

具有相同過濾器的查詢的後續執行將重用存儲在bitset中的信息,從而通過節省 IO 操作和 CPU 週期來加快查詢的執行速度。

建議在查詢中使用 filter 過濾器。

有關更多詳細信息,請參見:

  1. 喫透 | Elasticsearch filter和query的不同

  2. Elasticsearch 緩存深入詳解

7.7 合理設置刷新頻率

刷新頻率(refresh_interval)和段合併頻率與索引性能密切相關,此外,它們還會影響整個集羣的性能。

刷新頻率需要根據業務需要合理設置,尤其頻繁寫入的業務場景。

7.8 啓動慢查詢日誌

啓用慢查詢日誌記錄將有助於識別哪些查詢慢,以及可以採取哪些措施來改進它們,這對於通配符查詢特別有用。

推薦:

  1. Elasticsearch高級調優方法論之——根治慢查詢!

  2. 爲什麼Elasticsearch查詢變得這麼慢了?

7.9 增大ulimit大小

增加ulimit大小以允許最大文件數,這屬於非常常規的設置。

在 /etc/profile 下設置:

ulimit -n 65535

7.10 合理設置交互內存

當操作系統決定換出未使用的應用程序內存時,ElasticSearch 性能可能會受到影響。

通過 elasticsearch.yml 下配置:

bootstrap.mlockall: true  

7.11 禁用通配符模糊匹配刪除索引

禁止通過通配符查詢刪除所有索引。

爲確保某人不會對所有索引(* 或 _all)發出 DELETE 操作,設置如下:

PUT /_cluster/settings
{
  "persistent": {
    "action.destructive_requires_name"true
  }
}

此時如果我們再使用通配符刪除索引,舉例執行如下操作:

DELETE join_*

會報錯如下:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "illegal_argument_exception",
        "reason" : "Wildcard expressions or all indices are not allowed"
      }
    ],
    "type" : "illegal_argument_exception",
    "reason" : "Wildcard expressions or all indices are not allowed"
  },
  "status" : 400
}

8、常用指標監視 API

8.1 集羣健康狀態 API

GET _cluster/health?pretty

8.2 索引信息 API

GET _cat/indices?pretty&v

8.3 節點狀態 API

GET _nodes?pretty

8.4 主節點信息 API

GET _cat/master?pretty&v

8.5 分片分配、索引信息統計 API

GET _stats?pretty

8.6 節點狀態信息統計 API

統計節點的jvm,http,io統計信息。

GET _nodes/stats?pretty

大多數系統監視工具(如kibana、cerebro 等)都支持 Elasticsearc h的指標聚合。

建議使用此類工具持續監控集羣狀態信息。

9、小結

ElasticSearch 具有很好的默認配置以供新手快速上手、入門。但是,一旦到了線上業務實戰環境,就必須花費一些時間來調整設置以滿足實際業務功能要求以及性能指標要求。

建議你參考本文建議並結合官方文檔修改相關配置,以使得集羣整體部署最優。

加微信:elastic6,一起探討部署最佳實踐。

參考

https://medium.com/@abhidrona/elasticsearch-deployment-best-practices-d6c1323b25d7

https://t.zsxq.com/UVbQbee

推薦:

  1. 探究 | Elasticsearch集羣規模和容量規劃的底層邏輯

  2. Elasticsearch性能優化實戰指南

  3. 乾貨 | Elasticsearch開發人員最佳實戰指南

  4. Elasticsearch 常見的 8 種錯誤及最佳實踐

  5. 讓Elasticsearch飛起來!——性能優化實踐乾貨

  6. 全網首發!《 Elasticsearch 最少必要知識教程 V1.0 》低調發布

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章