天天看點

ES-部署

https://www.elastic.co/guide/cn/elasticsearch/guide/current/deploy.html

部署

硬體

按照正常的流程,你可能已經在自己的筆記本電腦或叢集上使用了 Elasticsearch。

但是當要部署 Elasticsearch 到生産環境時,有一些建議是你需要考慮的。

記憶體

如果有一種資源是

最先被耗盡的

,它可能是記憶體。

排序和聚合

都很耗記憶體,是以有足夠的堆空間來應付它們是很重要的。

即使使用的堆空間是比較小, 也能為作業系統檔案緩存提供額外的記憶體。因為 Lucene 使用的許多資料結構是基于磁盤的格式,Elasticsearch 利用作業系統緩存能産生很大效果。

  • 64 GB 記憶體的機器是非常理想的,
    • 大于64 GB 的機器也會有問題(

      不均衡

      )
  • 但是32 GB 和16 GB 機器也是很常見的。
  • 少于8 GB 會适得其反

CPUs

大多數 Elasticsearch 部署往往對 CPU 要求不高。是以,相對其它資源,具體配置多少個(CPU)不是那麼關鍵。你應該選擇具有多個核心的現代處理器,常見的叢集

使用兩到八個核的機器

如果你要在更快的 CPUs 和更多的核心之間選擇,

選擇更多的核心更好

硬碟

硬碟對所有的叢集都很重要,對大量寫入的叢集更是加倍重要(例如那些存儲日志資料的)。

硬碟是伺服器上最慢的子系統

,這意味着那些寫入量很大的叢集很容易讓硬碟飽和,使得它成為叢集的瓶頸。

  • 如果你負擔得起,SSD 是一個好的選擇。
  • 使用 RAID 0 是提高硬碟速度的有效途徑,對機械硬碟和 SSD 來說都是如此。沒有必要使用鏡像或其它 RAID 變體,因為高可用已經通過 replicas 内建于 Elasticsearch 之中。
RAID 0提高存儲性能的原理是把連續的資料分散到多個磁盤上存取,這樣,系統有資料請求就可以被多個磁盤并行的執行,每個磁盤執行屬于它自己的那部分資料請求。
ES-部署
- 避免使用網絡附加存儲(NAS)。

網絡

快速可靠的網絡顯然對分布式系統的性能是很重要的。

低延時能幫助確定節點間能容易的通訊,大帶寬能幫助分片移動和恢複。

現代資料中心網絡(1 GbE, 10 GbE)對絕大多數叢集都是足夠的。

即使資料中心們近在咫尺,也要避免叢集跨越多個資料中心。絕對要避免叢集跨越大的地理距離。

總則

成百 GB 的 RAM 和幾十個 CPU 核心

vs

在雲平台上串聯起成千的小虛拟機

  • 通常,選擇中配或者高配機器更好。
  • 避免使用低配機器

    , 因為你不會希望去管理擁有上千個節點的叢集,而且在這些低配機器上運作Elasticsearch 的開銷也是顯著的。
  • 避免使用真正的高配機器。

    它們通常會導緻資源使用不均衡(例如,所有的記憶體都被使用,但 CPU 卻沒有)而且在單機上運作多個節點時,會增加邏輯複雜度。

配置

Elasticsearch 已經有了 很好 的預設值,

特别是涉及到性能相關的配置或者選項

。 如果你有疑問,最好就不要動它。

其它資料庫可能需要調優,但總得來說,

Elasticsearch 不需要

如果你遇到了性能問題,解決方法通常是更好的資料布局或者更多的節點。 在 Elasticsearch 中很少有“神奇的配置項”, 如果存在,我們也已經幫你優化了!

指定名字

Elasticsearch 預設啟動的叢集名字叫 elasticsearch 。

你最好給你的生産環境的叢集改個名字,改名字的目的很簡單, 就是防止某人的筆記本電腦加入了叢集這種意外。你可以在你的

elasticsearch.yml

檔案中修改:

cluster.name: elasticsearch_production

同樣,最好也修改你的節點名字。就像你現在可能發現的那樣, Elasticsearch 會在你的節點啟動的時候随機給它指定一個名字。否則會帶來日志混亂等一些問題。

node.name: elasticsearch_005_data

路徑

預設情況下,Elasticsearch 會把插件、日志以及你最重要的資料放在安裝目錄下。這會帶來不幸的事故, 如果你重新安裝 Elasticsearch 的時候不小心把安裝目錄覆寫了。如果你不小心,你就可能把你的全部資料删掉了。

最好的選擇就是把你的資料目錄配置到安裝目錄以外的地方, 同樣你也可以選擇轉移你的插件和日志目錄。

# 你可以通過逗号分隔指定多個目錄。
# 資料可以儲存到多個不同的目錄, 如果将每個目錄分别挂載不同的硬碟,這可是一個簡單且高效實作一個軟磁盤陣列( RAID 0 )的辦法。
path.data: /path/to/data1,/path/to/data2 

# Path to log files:
path.logs: /path/to/logs

# Path to where plugins are installed:
path.plugins: /path/to/plugins
           

最小節點數

minimum_master_nodes

設定對你的叢集的穩定 極其 重要。 配置有助于防止腦裂(叢集中有兩個masters).

如果你的叢集發生了腦裂,那麼你的叢集就會處在丢失資料的危險中,因為主節點被認為是這個叢集的最高統治者,它決定了什麼時候新的索引可以建立,分片是如何移動的等等。

這個配置就是告訴 Elasticsearch 當沒有足夠 master 候選節點的時候,就不要進行 master 節點選舉,等 master 候選節點足夠了才進行選舉。

此設定應該始終被配置為 master 候選節點的法定個數(大多數個)。法定個數就是

( master 候選節點個數 / 2) + 1

固定配置

你可以在你的

elasticsearch.yml

檔案中這樣配置:

discovery.zen.minimum_master_nodes: 2

API修改

但是由于 ELasticsearch 是動态的,你可以很容易的添加和删除節點, 但是這會改變這個法定個數。 你不得不修改每一個索引節點的配置并且重新開機你的整個叢集隻是為了讓配置生效,這将是非常痛苦的一件事情。

基于這個原因,

minimum_master_nodes (還有一些其它配置)

允許通過 API 調用的方式動态進行配置。 當你的叢集線上運作的時候,你可以這樣修改配置:

PUT /_cluster/settings
{
    "persistent" : {
        "discovery.zen.minimum_master_nodes" : 2
    }
}
           

這将成為一個永久的配置,并且無論你配置項裡配置的如何,這個将優先生效。

當你添加和删除 master 節點的時候,你需要更改這個配置。

叢集恢複方面的配置

當你叢集重新開機時,幾個配置項影響你的分片恢複的表現。

首先,我們需要明白如果什麼也沒配置将會發生什麼。

想象一下假設你有

10 個節點,每個節點隻儲存一個分片,這個分片是一個主分片或者是一個副本分片

,或者說有一個有 5 個主分片/1 個副本分片的索引。

有時你需要為整個叢集做離線維護(比如,為了安裝一個新的驅動程式), 當你重新開機你的叢集,

恰巧出現了 5 個節點已經啟動,還有 5 個還沒啟動的場景

假設其它 5 個節點出問題,或者他們根本沒有收到立即重新開機的指令。不管什麼原因,你有 5 個節點線上上,這五個節點會互相通信,

選出一個 master,進而形成一個叢集

。 他們注意到資料不再均勻分布,因為有 5 個節點在叢集中丢失了,是以他們之間會

立即啟動分片複制

最後,你的其它 5 個節點打開加入了叢集。這些節點會發現 它們 的資料正在被複制到其他節點,

是以他們删除本地資料(因為這份資料要麼是多餘的,要麼是過時的)

。 然後整個叢集重新進行平衡,因為叢集的大小已經從 5 變成了 10。

在整個過程中,你的節點會消耗磁盤和網絡帶寬,來回移動資料,因為沒有更好的辦法。

對于有 TB 資料的大叢集, 這種無用的資料傳輸需要 很長時間 。

如果等待所有的節點重新開機好了,整個叢集再上線,所有的本地的資料都不需要移動。

現在我們知道問題的所在了,我們可以修改一些設定來緩解它。 首先我們要給 ELasticsearch 一個嚴格的限制:

# 阻止 Elasticsearch 在存在至少 8 個節點(資料節點或者 master 節點)之前進行資料恢複
# 這意味着至少要有 8 個節點,該叢集才可用。
gateway.recover_after_nodes: 8


## 等待如下兩個條件中任意一個滿足,再進行資料恢複
# 等待叢集至少存在 10 個節點
gateway.expected_nodes: 10
# 等待 5 分鐘
gateway.recover_after_time: 5m
           

使用單點傳播代替多點傳播

Elasticsearch 預設被配置為使用單點傳播發現,以防止節點無意中加入叢集。

隻有在同一台機器上運作的節點才會自動組成叢集。

使用單點傳播,你可以為 Elasticsearch 提供一些它應該去嘗試連接配接的節點清單。 當一個節點聯系到單點傳播清單中的成員時,它就會得到整個叢集所有節點的狀态,然後它會聯系 master 節點,并加入叢集。

這意味着你的單點傳播清單不需要包含你的叢集中的所有節點, 它隻是需要足夠的節點,當一個新節點聯系上其中一個并且說上話就可以了。如果你使用 master 候選節點作為單點傳播清單,你隻要列出三個就可以了。 這個配置在 elasticsearch.yml 檔案中:

discovery.zen.ping.unicast.hosts: ["host1", "host2:port"]
           

不要修改如下配置

垃圾回收器

不要更改預設的垃圾回收器!

線程池

多人 喜歡 調整線程池。 無論什麼原因,人們都對增加線程數無法抵抗。

索引太多了?增加線程!

搜尋太多了?增加線程!

節點空閑率低于 95%?增加線程!

  • 如果你有 8 個核,你可以同時運作的隻有 8 個線程,隻配置設定 8 個線程給任何特定的線程池是有道理的。
  • 搜尋線程池設定的大一點,配置為

    int(( 核心數 * 3 )/ 2 )+ 1

  • 最多設定成核心數的兩倍,再多了都是浪費。

堆記憶體:大小和交換

Elasticsearch 預設安裝後設定的堆記憶體是 1 GB。對于任何一個業務部署來說, 這個設定都太小了。如果你正在使用這些預設堆記憶體配置,您的叢集可能會出現問題。

這裡有兩種方式修改 Elasticsearch 的堆記憶體。最簡單的一個方法就是指定

ES_HEAP_SIZE 環境變量

。服務程序在啟動時候會讀取這個變量,并相應的設定堆的大小。

export ES_HEAP_SIZE=10g

你也可以通過指令行參數的形式,在程式啟動的時候把記憶體大小傳遞給它,如果你覺得這樣更簡單的話:

./bin/elasticsearch -Xmx10g -Xms10g

確定

堆記憶體最小值( Xms )與最大值( Xmx )的大小是相同的

,防止程式在運作時堆記憶體大小伸縮, 這是一個很耗系統資源的過程。

把你的記憶體的(少于)一半給Lucene

一個常見的問題是給 Elasticsearch 配置設定的記憶體 太 大了。假設你有一個 64 GB 記憶體的機器, 天啊,我要把 64 GB 記憶體全都給 Elasticsearch。因為越多越好啊!

當然,記憶體對于 Elasticsearch 來說絕對是重要的,它可以被許多記憶體資料結構使用來提供更快的操作。但是說到這裡, 還有另外一個記憶體消耗大戶 非堆記憶體 (off-heap):Lucene。

Lucene 被設計為可以

利用作業系統底層機制來緩存記憶體資料結構

。 Lucene 的段是分别存儲到單個檔案中的。因為段是不可變的,這些檔案也都不會變化,這是對緩存友好的,同時作業系統也會把這些段檔案緩存起來,以便更快的通路。

Lucene 的性能取決于和作業系統的互相作用。如果你把所有的記憶體都配置設定給 Elasticsearch 的堆記憶體,那将不會有剩餘的記憶體交給 Lucene。 這将嚴重地影響全文檢索的性能。

标準的建議是把 50% 的可用記憶體作為 Elasticsearch 的堆記憶體,保留剩下的 50%。當然它也不會被浪費,Lucene 會很樂意利用起餘下的記憶體。

如果你不需要對分詞字元串做

聚合計算(例如,不需要 fielddata )

可以考慮降低堆記憶體。

堆記憶體越小,Elasticsearch(更快的 GC)和 Lucene(更多的記憶體用于緩存)的性能越好。

不要超過32GB

這裡有另外一個原因不配置設定大記憶體給 Elasticsearch。

事實上, JVM 在記憶體小于 32 GB 的時候會采用一個記憶體對象指針壓縮技術。

在 Java 中,所有的對象都配置設定在堆上,并通過一個指針進行引用。

普通對象指針(OOP)指向這些對象,通常為 CPU 字長 的大小:32 位或 64 位,取決于你的處理器。

指針引用的就是這個 OOP 值的位元組位置。

對于 32 位的系統,意味着堆記憶體大小最大為 4 GB。對于 64 位的系統, 可以使用更大的記憶體,但是 64 位的指針意味着更大的浪費,因為你的指針本身大了。

Java 使用一個叫作

記憶體指針壓縮(compressed oops)

的技術來解決這個問題。 它的指針不再表示對象在記憶體中的精确位置,而是表示

偏移量

。這意味着 32 位的指針可以引用 40 億個 對象 , 而不是 40 億個位元組。最終, 也就是說堆記憶體增長到 32 GB 的實體記憶體,也可以用 32 位的指針表示。

假設你有個機器有 128 GB 的記憶體,你可以建立兩個節點,每個節點記憶體配置設定不超過 32 GB。 也就是說不超過 64 GB 記憶體給 ES 的堆記憶體,剩下的超過 64 GB 的記憶體給 Lucene。

如果你選擇這一種,你需要配置

cluster.routing.allocation.same_shard.host: true

。 這會防止同一個分片(shard)的主副本存在同一個實體機上。

Swapping是性能的墳墓

  • 最好的辦法就是在你的作業系統中完全禁用 swap。這樣可以暫時禁用:

    sudo swapoff -a

    .
  • 如果需要永久禁用,你可能需要修改

    /etc/fstab

    檔案,
  • 如果你并不打算完全禁用 swap,也可以選擇

    降低 swappiness 的值

    。 這個值決定作業系統交換記憶體的頻率。 這可以預防正常情況下發生交換,但仍允許作業系統在緊急情況下發生交換。

    vm.swappiness = 1

  • 如果上面的方法都不合适,在你的

    elasticsearch.yml

    檔案中,設定如下:

    bootstrap.mlockall: true

    ,它的作用就是允許 JVM 鎖住記憶體,禁止作業系統交換出去。

檔案描述符合MMap

Lucene 使用了 大量的 檔案。 同時,Elasticsearch 在節點和 HTTP 用戶端之間進行通信也使用了大量的套接字(注:sockets)。 所有這一切都需要足夠的檔案描述符。

可悲的是,許多現代的 Linux 發行版本,

每個程序預設允許一個微不足道的 1024 檔案描述符

。這對一個小的 Elasticsearch 節點來說實在是太 低 了,更不用說一個處理數以百計索引的節點。

你應該增加你的檔案描述符,設定一個很大的值,如 64,000。這個過程困難得讓人惱火,它高度依賴于你的特定作業系統和分布。

一旦你認為已經改變了它,檢查 Elasticsearch,以確定它的真的起作用并且有足夠的檔案描述符:

GET /_nodes/process

{
   "cluster_name": "elasticsearch__zach",
   "nodes": {
      "TGn9iO2_QQKb0kavcLbnDw": {
         "name": "Zach",
         "transport_address": "inet[/192.168.1.131:9300]",
         "host": "zacharys-air",
         "ip": "192.168.1.131",
         "version": "2.0.0-SNAPSHOT",
         "build": "612f461",
         "http_address": "inet[/192.168.1.131:9200]",
         "process": {
            "refresh_interval_in_millis": 1000,
            "id": 19808,
            "max_file_descriptors": 64000,  //顯示 Elasticsearch 程序可以通路的可用檔案描述符數量。
            "mlockall": true
         }
      }
   }
}
           

Elasticsearch 對各種檔案混合使用了

NioFs( 注:非阻塞檔案系統)和 MMapFs ( 注:記憶體映射檔案系統

.請確定你配置的最大映射數量,以便有足夠的虛拟記憶體可用于 mmapped 檔案。

這可以暫時設定:

sysctl -w vm.max_map_count=262144

或者在

/etc/sysctl.conf

通過修改

vm.max_map_count

永久設定它

繼續閱讀