天天看點

Elasticsearch 生産環境叢集部署最佳實踐—Elastic Stack 實戰手冊

Elasticsearch 生産環境叢集部署最佳實踐—Elastic Stack 實戰手冊
https://developer.aliyun.com/topic/download?id=1295 · 更多精彩内容,請下載下傳閱讀全本《Elastic Stack實戰手冊》 https://developer.aliyun.com/topic/download?id=1295 https://developer.aliyun.com/topic/es100 · 加入創作人行列,一起交流碰撞,參與技術圈年度盛事吧 https://developer.aliyun.com/topic/es100

創作人:銘毅天下

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

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

記憶體

Elasticsearch 和 Lucene 都是 Java 語言編寫,這意味着我們必須注意堆記憶體的設定。

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

但請注意,過多的堆可能會使垃圾回收暫停時間過長。請勿将堆記憶體的最大值設定為 JVM 用于壓縮對象指針(壓縮的 oops)的臨界值之上,确切的臨界值有所不同,但不要超過 32 GB

常見記憶體配置坑 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 生産環境叢集部署最佳實踐—Elastic Stack 實戰手冊

可以通過以下方式配置 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           

CPU

運作複雜的緩存查詢、密集寫入資料都需要大量的 CPU,是以選擇正确的查詢類型以及漸進的寫入政策至關重要。

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

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

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

分片數

分片是 Elasticsearch 在叢集内分發資料的機關。叢集發生故障再恢複平衡的速度,取決于分片的大小、分片數量、網絡以及磁盤性能。

在 Elasticsearch 中,每個查詢在每個分片的單個線程中執行。但是,可以并行處理多個分片。針對同一分片的多個查詢和聚合也可以并行處理。這意味着在不涉及緩存的情況下,最小查詢延遲将取決于資料、查詢類型以及分片的大小三個因素。

設定很多小分片 VS 設定很少大分片?

  • 查詢很多小分片,導緻每個分片能做到快速響應,但是由于需要按順序排隊和處理結果彙集。是以不一定比查詢少量的大分片快。
  • 如果存在多個并發查詢,那麼擁有大量小分片也會降低查詢吞吐量

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

分片數設定

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

對于叢集而言,分片數多了以後,索引和分片管理,可能會使主節點超載,并可能會導緻叢集無響應,甚至導緻叢集當機。

建議:為主節點(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

副本

Elasticsearch 通過副本實作叢集的高可用性,資料在資料節點之間複制,以實作主分片資料的備份,是以即便部分節點因異常下線,也不會導緻資料丢失。

預設情況下,副本數為 1,但可以根據産品高可用要求将其增加。副本越多,資料的容災性越高。

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

銘毅提醒:

  • 實際副本數增多,提高查詢性能建議結合叢集做下測試,我實測過效果不明顯。
  • 副本數增多,意味着磁盤存儲要加倍,也考驗硬碟空間和磁盤預算。

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

冷熱叢集架構配置

根據産品業務資料特定和需求,我們可以将資料分為熱資料和冷資料,這是冷熱叢集架構的前提。

通路頻率更高的索引,可以配置設定更多更高配(如:SSD)的資料節點,而通路頻率較低的索引可以配置設定低配(如:機械磁盤)資料節點。

冷熱叢集架構對于存儲,諸如應用程式日志或網際網路實時采集資料(基于時間序列資料)特别有用。

資料遷移政策:通過運作定時任務,來實作定期将索引移動到不同類型的節點。

具體實作:Curator 工具或借助 ILM 索引生命周期管理。

熱節點

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

因為這些熱節點資料通常傾向于最頻繁地查詢。熱資料的操作會占用大量 CPU 和 IO 資源,是以對應伺服器需要功能強大(高配)并附加 SSD 存儲支援。

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

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

冷節點(或稱暖節點)

冷節點是對标熱節點的一種資料節點,旨在處理大量不太經常查詢的隻讀索引資料。由于這些索引是隻讀的,是以冷節點傾向于使用普通機械磁盤而非 SSD 磁盤。

與熱節點對标,也建議:最少 3 個冷節點以實作高可用性。同樣需要注意的是,若叢集規模非常大,可能需要更多節點才能滿足性能要求。

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

強調一下:CPU 和 記憶體的配置設定最終需要你通過使用與生産環境中類似的環境借助 esrally 性能測試工具測試确定,而不是直接參考各種最佳實踐拍腦袋而定。

有關熱節點和熱節點的更多詳細資訊,請參見: https://www.elastic.co/blog/hot-warm-architecture-in-elasticsearch-5-x

節點角色劃分

Elasticsearch 節點核心可分為三類:主節點、資料節點、協調節點。

主節點

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

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

主節點職責:存儲叢集狀态資訊、分片配置設定管理等。

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

資料節點

資料節點職責:CURD、搜尋以及聚合相關的操作。

這些操作一般都是 IO、記憶體、CPU 密集型。

協調節點

協調節點職責:類似負載平衡器,主要工作是将搜尋任務分發到相關的資料節點,并收集所有結果,然後再将它們彙總并傳回給用戶端應用程式。

節點配置參考

下表參見官方部落格 PPT

角色 描述 存儲 計算 網絡
存儲和檢索資料 極高
管理叢集狀态
Ingest 節點 轉換輸入資料
機器學習節點 機器學習
請求轉發和合并檢索結果

不同節點角色配置如下

必須配置到:elasticsearch.yml 中。

node.master:true node.data:false            
node.master:false node.data:true            
node.master:false node.data:false           

故障排除提示

Elasticsearch 的性能在很大程度上取決于主控端資源情況。CPU、記憶體使用率和磁盤 IO 是每個 Elasticsearch 節點的基本名額。建議你在CPU使用率激增時檢視 Java 虛拟機(JVM)名額。

堆記憶體使用率高

高堆記憶體使用率壓力以兩種方式影響叢集性能:

堆記憶體壓力上升到 75% 及更高

  • 剩餘可用記憶體更少,并且叢集現在還需要花費一些 CPU 資源以通過垃圾回收來回收記憶體。
  • 在啟用垃圾收集時,這些 CPU 周期不可用于處理使用者請求。結果,随着系統變得越來越受資源限制,使用者請求的響應時間增加。

堆記憶體壓力繼續上升并達到接近 100%

  • 将使用更具侵略性的垃圾收集形式,這将反過來極大地影響叢集響應時間。
  • 索引響應時間度量标準表明,高堆記憶體壓力會嚴重影響性能。

非堆記憶體使用率增長

JVM 外非堆記憶體的增長,吞噬了用于頁面緩存的記憶體,并可能導緻核心級 OOM。

監控磁盤 IO

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

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

  • 優化分片數量及其大小
  • 段合并政策優化
  • 更換普通磁盤為 SSD 磁盤
  • 添加更多節點

合理設定預警

對于依賴搜尋的應用程式,使用者體驗與搜尋請求的等待時間長短相關。

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

  • 構造查詢方式不合理
  • Elasticsearch 叢集配置不合理
  • JVM 記憶體和垃圾回收問題
  • 磁盤 IO 等

查詢延遲是直接影響使用者體驗的名額,是以請確定在其上放置一些預警操作。

舉例:線上實戰問題:

Elasticsearch 生産環境叢集部署最佳實踐—Elastic Stack 實戰手冊

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

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

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

合理配置緩存

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

這意味着在第一次執行過濾查詢時,Elasticsearch 将查找與過濾器比對的文檔,并使用該資訊建構名為“bitset”的結構。

存儲在 bitset 中的資料包含文檔辨別符以及給定文檔是否與過濾器比對。

具有相同過濾器的查詢的後續執行将重用存儲在 bitset 中的資訊,進而通過節省 IO 操作和 CPU 周期來加快查詢的執行速度。

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

合理設定重新整理頻率

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

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

啟動慢查詢日志

啟用慢查詢日志記錄将有助于識别哪些查詢慢,以及可以采取哪些措施來改進它們,這對于通配符查詢特别有用。

增大 ulimit 大小

增加 ulimit 大小以允許最大檔案數,這屬于非常正常的設定。

在 /etc/profile 下設定:

ulimit -n 65535           

合理設定互動記憶體

當作業系統決定換出未使用的應用程式記憶體時,ElasticSearch 性能可能會受到影響。

通過 elasticsearch.yml 下配置:

bootstrap.mlockall: true             

禁用通配符模糊比對删除索引

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

為確定某人不會對所有索引(* 或 _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
}           

常用名額監視 API

叢集健康狀态 API

GET _cluster/health?pretty           

索引資訊 API

GET _cat/indices?pretty&v           

節點狀态 API

GET _nodes?pretty           

主節點資訊 API

GET _cat/master?pretty&v           

分片配置設定、索引資訊統計 API

GET _stats?pretty           

節點狀态資訊統計 API

統計節點的 jvm,http,IO 統計資訊。

GET _nodes/stats?pretty           

大多數系統監視工具(如 Kibana、cerebro 等)都支援 Elasticsearc h的名額聚合。

建議使用此類工具持續監控叢集狀态資訊。

小結

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

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