1. 程式人生 > >生產環境elasticsearch的配置建議

生產環境elasticsearch的配置建議

以下主要來自官方文件,主要分為幾塊:

硬體方面

記憶體

首先最重要的資源是記憶體,排序和聚合都可能導致記憶體匱乏,因此足夠的堆空間來容納這些是重要的。即使堆比較小,也要給作業系統快取記憶體提供額外的記憶體,因為Lucene使用的許多資料結構是基於磁碟的格式,Elasticsearch利用作業系統快取有很大的影響。
64GB RAM的機器是最理想的,但32GB和16GB機器也很常見。少於8GB往往適得其反(你最終需要許多,許多小機器),大於64GB可能會有問題,我們將在討論在堆:大小和交換。

CPU

大多數Elasticsearch部署往往對CPU要求很不大。因此,確切的處理器設定比其他資源更重要,應該選擇具有多個核心的現代處理器。通用叢集使用2到8核機器。
如果需要在較快的CPU或更多核之間進行選擇,請選擇更多核。 多核提供的額外併發將遠遠超過稍快的時鐘速度。

硬碟

磁碟對於所有叢集都很重要,尤其是對於索引很重的叢集(例如攝取日誌資料的磁碟)。 磁碟是伺服器中最慢的子系統,這意味著大量寫入的群集可以輕鬆地飽和其磁碟,這反過來成為群集的瓶頸。

如果你能買得起SSD,他們遠遠優於任何旋轉磁碟。 支援SSD的節點看到查詢和索引效能方面的提升。
如果使用旋轉磁碟,請嘗試獲取儘可能最快的磁碟(高效能伺服器磁碟,15k轉速驅動器)。
使用RAID 0是提高磁碟速度的有效方法,適用於旋轉磁碟和SSD。 沒有必要使用RAID的映象或奇偶校驗變體,因為高可用性是通過副本建立到Elasticsearch中。
最後,避免網路連線儲存(NAS)。 NAS通常較慢,顯示較大的延遲,平均延遲的偏差較大,並且是單點故障。

檢查IO排程程式
如果使用SSD,請確保正確配置您的OS I/O排程程式。 當將資料寫入磁碟時,I/O排程程式將確定該資料何時實際傳送到磁碟。 大多數排程的預設值是名為cfq(Completely Fair Queuing)。
此排程程式為每個程序分配時間片,然後優化這些不同佇列到磁碟的傳遞。 他是針對旋轉磁碟介質的優化:旋轉盤的性質意味著根據物理佈局將資料寫入磁碟更高效。
然而,這對於SSD是低效的,因為SSD不涉及磁碟旋轉。 相反,應該使用deadline或noop。 deadline排程根據寫入已經等待的時間進行優化,noop只是一個簡單的FIFO佇列。
這種簡單的變化可以產生巨大的影響 我們已經看到,通過使用正確的排程程式,寫入吞吐量提高了500倍。cat /sys/block/sda/queue/scheduler命令檢視,修改參照http://www.nuodb.com/techblog/tuning-linux-io-scheduler-ssds

網路

快速和可靠的網路對於分散式系統中的效能顯然是重要的。低延遲有助於確保節點可以輕鬆地進行通訊,而高頻寬有助於分段移動和恢復。現代資料中心網路(1GbE,10GbE)對於絕大多數叢集都是足夠的。
避免跨越多個數據中心的群集,即使資料中心位置非常接近。絕對避免跨越大地理距離的叢集。
Elasticsearch叢集假定所有節點相等,而不是一半的節點距離另一個數據中心中有150ms。較大的延遲往往會加劇分散式系統中的問題,並使除錯和解決更加困難。
與NAS引數類似,每個人都聲稱資料中心之間的管道是穩健的和低延遲。(吹牛)。從我們的經驗,管理跨資料中心叢集的麻煩就是浪費成本。

其他

現在可以獲得真正巨大的機器如數百GB的RAM和幾十個CPU核心。 另外也可以在雲平臺(如EC2)中啟動數千個小型虛擬機器。 哪種方法最好?
一般來說,最好選擇中到大盒子。 避免使用小型機器,因為您不想管理具有一千個節點的叢集,而簡單執行Elasticsearch的開銷在這種小型機器上更為明顯。
同時,避免真正巨大的機器。 它們通常導致資源使用不平衡(例如,所有記憶體正在使用,但沒有CPU),並且如果您必須為每臺機器執行多個節點,可能會增加後期的運維複雜性。

作業系統

較大的檔案描述符

Lucene使用了非常大量的檔案。 並且Elasticsearch使用大量的套接字在節點和HTTP客戶端之間進行通訊。 所有這些都需要可用的檔案描述符。
可悲的是,許多現代的Linux發行版每個程序允許一個不允許的1024個檔案描述符。 這對於一個小的Elasticsearch節點來說太低了,更不用說處理數百個索引的節點了。
您應該將檔案描述符計數增加到非常大的值,例如64,000。 這個過程是令人惱火的困難,高度依賴於你的特定作業系統和分佈。 請查閱作業系統的文件以確定如何更改允許的檔案描述符計數。
可以使用http://ip:port/_nodes/stats介面process中的open_file_descriptors和max_file_descriptors進行檢視。

設定MMap

Elasticsearch還針對各種檔案使用NioFS和MMapFS的混合。 確保配置最大對映計數,以便有足夠的虛擬記憶體可用於mmapped檔案。 這可以臨時設定

sysctl -w vm.max_map_count=655300

或者在/etc/sysctl.conf下永久設定vm.max_map_count。檢視設定

cat /proc/sys/vm/max_map_count

管理工具

叢集管理請使用叢集管理工具(Puppet, Chef, Ansible)。配置管理工具通過自動化配置更改過程來幫助使您的叢集一致,它可能需要一些時間來設定和學習,但隨著時間的推移,會發現他是值得的。

JVM虛擬機器

除非Elasticsearch網站上另有說明,否則應始終執行最新版本的Java虛擬機器(JVM)。 Elasticsearch和Lucene都是比較苛刻的軟體。 Lucene的單元和整合測試通常暴露JVM本身的錯誤。這些錯誤的範圍可以從輕微的煩惱到嚴重的segfaults,所以最好是使用最新版本的JVM儘可能。
Java8要好於Java7.Java6不再受支援。可以接受Oracle或OpenJDK。它們的效能和穩定性相當。
如果您的應用程式是用Java編寫的,並且正在使用傳輸客戶端或節點客戶端,請確保執行應用程式的JVM與伺服器JVM相同。在Elasticsearch中的幾個位置,使用Java的本機序列化(IP地址,異常等)。不幸的是,Oracle已知改變小版本之間的序列化格式,導致奇怪的錯誤。這種情況很少發生,但最佳做法是保持客戶端和伺服器之間的JVM版本相同。

請不要調整JVM設定

JVM暴露了幾十個甚至數百個引數和配置。 它們允許您調整和調整JVM的幾乎每個方面。但是建議不使用自定義JVM設定。 Elasticsearch是一個複雜的軟體,目前的JVM設定已經調整了多年的實際使用。
很容易調整引數,但是會產生難以測量的不透明效果,並最終使群集失去緩慢、不穩定,乃至混亂。 當除錯叢集時,第一步通常是刪除所有自定義配置。 大約一半的時間,這個能恢復穩定性和效能。

請不要修改垃圾收集器

Elasticsearch的預設GC是併發標記和掃描(CMS)。此GC與應用程式的執行同時執行,以便它可以最小化暫停。但是,它有兩個stop-world的階段。它也是收集大堆的麻煩。
儘管有這些缺點,它是目前最好的GC的低延遲伺服器軟體像Elasticsearch。官方建議是使用CMS。
有一個更新的GC稱為垃圾第一GC(G1GC)。這個較新的GC設計為最小化暫停甚至超過CMS,並在大堆上操作。它通過將堆分成區域並預測哪些區域包含最多的可回收空間來工作。通過首先收集這些區域(垃圾優先),它可以最小化停頓並在非常大的堆上操作。聽起來不錯,但不幸的是,G1GC仍然是新的,有很多新的bug。這些錯誤通常是segfault型別的,並將導致嚴重崩潰。 Lucene測試套件對GC演算法是殘酷的,看起來G1GC還沒有解決這個問題。
我們總有一天會推薦G1GC,但現在它不夠穩定,不足以滿足Elasticsearch和Lucene的需求。

給lucene留下一半的記憶體空間

一個常見的問題是配置一個太大的堆。你有一個64GB的機器,並且你想給Elasticsearch所有64GB的記憶體。更多更好?!堆對Elasticsearch絕對重要,它被許多記憶體資料結構使用以提供快速操作。但是還有另一個主要的記憶體使用者是堆:Lucene。
Lucene旨在利用底層作業系統來快取記憶體中的資料結構。 Lucene段儲存在單獨的檔案中,因為段是不可變的,所以這些檔案從不改變。這使得它們非常易於快取,並且底層作業系統將適合的保持segment駐留在記憶體中以便更快地訪問。這些段包括反向索引(用於全文搜尋)和docvalues(用於聚合)。Lucene的效能依賴於與作業系統的這種互動。但是如果你給Elasticsearch的堆提供所有可用的記憶體,Lucene就不會有任何剩餘的記憶體。這會嚴重影響效能。
標準建議是給Elasticsearch堆提供50%的可用記憶體,同時保留其他50%的空閒記憶體。它不會不使用; Lucene會愉快地吞噬剩下的任何東西。
如果你不是聚合在分析的字串欄位(例如你不需要fielddata),你可以考慮降低堆更多。你可以做的堆越小,你可以期望從Elasticsearch(更快的GC)和Lucene(更多的記憶體快取)更好的效能。

不要超過32G

事實證明,當堆大小小於32GB時,HotSpot JVM使用一個技巧來壓縮物件指標。可以通過-XX:+PrintFlagsFinal來檢視,在es2.2.0後不用設定,啟動後會列印compressed ordinary object pointers [true]
在Java中,所有物件都在堆上分配並由指標引用。Ordinary object pointers(OOP)指向這些物件,並且通常是CPU本地字的大小:32位或64位,取決於處理器。指標引用值的確切位元組位置。 對於32位系統,這最大堆大小為4GB。對於64位系統,堆大小可以變得更大,但64位指標的開銷意味著更多的浪費空間,因為指標更大。並且比浪費的空間更糟,當在主儲存器和各種快取記憶體(LLC,L1等)之間移動值時,較大的指標佔用更多的頻寬。
Java使用一個名為compress oops的技巧來解決這個問題。指標不是指向儲存器中的精確位元組位置,而是引用物件偏移。這意味著32位指標可以引用四十億個物件,而不是40億位元組。最終,這意味著堆可以增長到大約32 GB的物理大小,同時仍然使用32位指標。
一旦你超越32GB邊界,指標切換回Ordinary object pointers。每個指標的大小增加,使用更多的CPU記憶體頻寬,並且您有效地丟失了記憶體。事實上,它需要直到大約40到50GB的分配的堆,你有一個堆的相同有效記憶體剛剛低於32GB使用壓縮oops。所以即使你有記憶體,儘量避免跨越32 GB堆邊界。它浪費記憶體,降低CPU效能,並使GC與大堆爭奪。

避免過大的使用記憶體

32G這個臨界值是相當重要的。但是如果你的機器有很多記憶體時,你改怎麼?畢竟現在有512-768GB RAM的超級伺服器變得越來越普遍。
1、首先,我們建議避免使用這種大型機器(參見硬體)。但如果你已經有這種機器,則有兩個實用的選擇:
你大部分是全文搜尋嗎?考慮給Elasticsearch提供4-32 GB,讓Lucene通過作業系統檔案系統快取使用剩餘的記憶體。所有的記憶體將快取段,並導致令人驚異的快速全文搜尋。你做了很多排序/聚合?大多數聚合是在數字,日期,geo_points和not_analyzed字串?你很幸運!給Elasticsearch從4-32 GB的記憶體,並留下其餘的作業系統快取在記憶體中的文件值。
2、你在分析的字串上是否做了很多排序/聚合(例如word-tags 或者SigTerms等)?不幸的是,這意味著你需要fielddata,這意味著你需要堆空間。作為一個節點具有超過512GB的RAM的替換方案,請考慮在單個機器上執行兩個或多個節點。仍然堅持50%的規則。因此,如果您的機器有128 GB的RAM,執行兩個節點,每個節點只有32GB。這意味著少於64GB將用於堆記憶體,並且Lucene將剩餘64GB以上。如果選擇此選項,請在配置中設定

cluster.routing.allocation.same_shard.host:true

這將防止主分片和副本分片共同駐留到同一物理機器(因為這會移除副本高可用性的好處)。

swapping是效能的死穴

它應該是顯而易見的,但它明確拼寫出來:將主記憶體交換到磁碟會破壞伺服器效能。 記憶體中操作是需要快速執行的操作。如果記憶體交換到磁碟,100微秒操作將花費10毫秒。 現在重複所有其他10us操作的延遲增加。 不難看出為什麼交換對於效能來說是可怕的。
1、最好的辦法是在系統上完全禁用交換。 這可以臨時完成:

sudo swapoff -a。

要永久禁用則需要編輯/etc/fstab。請查閱作業系統的文件。
2、如果完全禁用交換不是一個選項,您可以嘗試

sysctl vm.swappiness = 1(檢視cat /proc/sys/vm/swappiness)

這個設定控制作業系統如何積極地嘗試交換記憶體。 以防止在正常情況下交換,但仍然允許作業系統在緊急情況下交換。swappiness值1比0好,因為在一些核心版本上,swappiness為0可以呼叫OOM-killer。
3、最後,如果兩種方法都不可能,就應該啟用mlockall。 這允許JVM鎖定其記憶體,並防止它被作業系統交換。 可以在elasticsearch.yml中設定:

bootstrap.mlockall: true

ES引數配置

禁止調整執行緒池

每個人都喜歡調整執行緒池。無論什麼原因,似乎人們不能抵抗增加執行緒數。索引很多?更多主題!很多搜尋?更多主題!節點空閒95%的時間?更多主題!
Elasticsearch中的預設執行緒池設定非常明智。對於所有執行緒池(除了搜尋),threadcount設定為CPU核心數。如果你有八個核心,你只能同時執行八個執行緒。對任何特定的執行緒池只分配8個執行緒是有意義的。
搜尋獲得更大的執行緒池,並配置為int((#of cores * 3)/ 2)+ 1。

1\你可能會認為某些執行緒可能阻塞(例如在磁碟I/O操作上),這就是為什麼你需要更多執行緒。這不是Elasticsearch中的問題:大多數磁碟I/O由Lucene管理的執行緒處理,而不是Elasticsearch。
2\此外,執行緒池通過在彼此之間傳遞工作來協作。你不需要擔心網路執行緒阻塞,因為它正在等待磁碟寫入。網路執行緒將很久以前將該工作單元交給另一個執行緒池,並返回到網路。
3\最後,你的過程的計算能力是有限的。擁有更多的執行緒只是迫使處理器切換執行緒上下文。處理器每次只能執行一個執行緒,因此,當它需要切換到不同的執行緒時,它會儲存當前狀態(暫存器等)並載入另一個執行緒。如果你幸運,交換機將發生在同一個核心。如果你不幸運,交換機可能遷移到不同的核心,並且需要在核間通訊總線上傳輸。這種上下文切換通過執行管理內務處理來完成周期;估計可以在現代CPU上高達30μs。因此,除非執行緒將被阻塞超過30μs,很可能這個時間將更好地用於只是處理和完成提前。
人們通常將執行緒池設定為愚蠢的值。在8核機器上,我們執行的配置與60,100或甚至1000執行緒。這些設定將簡單地破壞CPU比實際工作完成。
所以下次你想調整一個執行緒池,請拒絕。如果你絕對不能抗拒,請記住你的核心數量,可以設定計數加倍。

設定叢集和節點名稱

Elasticseach預設情況下啟動名為elasticsearch的叢集。 明智的做法是將生產叢集重新命名為其名稱,只是為了防止有人的膝上型電腦加入群集導致事故。 一個簡單的名稱更改可以省卻大量煩惱。
在elasticsearch.yml檔案中更改

cluster.name: elasticsearch_production_name

同樣的修改節點名稱也是明智的選擇,不需要es自動給你分配某些奇怪的名字,更加便於記憶;更重要的是避免重啟之後又隨機生成一個其他的名字,這會導致更多的不必要的問題。
在elasticsearch.yml檔案中更改

node.name: elasticsearch_005_data

設定路徑

預設情況下,Elasticsearch會將外掛、日誌和最重要的資料放在安裝目錄中。 這可能會導致不幸的事故,由此安裝目錄會被新安裝的Elasticsearch意外覆蓋!!!
最好的辦法是將資料目錄重定位到安裝位置之外,當然也包括外掛和日誌目錄。

path.data: /path/to/data1,/path/to/data2 #可以通過逗號指定多個目錄存放
path.logs: /path/to/logs
path.plugins: /path/to/plugins

資料可以儲存到多個目錄,如果每個目錄安裝在不同的硬碟驅動器上,這就類似於軟體方式實現了RAID0. Elasticsearch將自動在不同目錄之間分條資料,提高效能。

設定minimum_master_nodes

minimum_master_nodes設定對群集的穩定性非常重要,這個設定有助於防止split brains(腦裂,在單個叢集中存在兩個主節點)
一旦發生裂腦,叢集就很可能會丟失資料。 因為master被認為是群集的最高統治者,所以它決定什麼時候可以建立新的索引,如何移動碎片,等等。 如果你有兩個master,資料完整性變得危險,因為這兩個節點認為他們自己是負責人。
這個設定是意思是告訴Elasticsearch不選擇主節點,除非有足夠的主節點可用節點。 只有這樣,才會舉行選舉。

此設定應始終配置採用quorum原理,一般是(能夠成為master的節點數/ 2)+ 1.這裡有一些示例:
1、如果你有10個常規節點(可以儲存資料,可以成為主機),quorum為6。
2、如果您有3個專用主節點和一百個資料節點,則quorum為2,因為您只需要統計只有符合主節點的節點。
3、如果你有兩個常規節點,你是在一個難題。 quorum將為2,但這意味著一個節點的丟失將使您的叢集不可操作。 設定為1將允許您的群集執行,但不能防止裂腦。 在這種情況下最好有至少三個節點。
此設定可以在elasticsearch.yml檔案中配置:discovery.zen.minimum_master_nodes: 2 (每個節點都需要配置並且一致)
當然也可以通過動態API呼叫進行配置。 您可以在群集聯機時更改設定:

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

設定recover settings

先了解沒有設定的情況下es是怎麼工作的。
假設您有十個節點,每個節點在5個主/1副本索引中儲存單個分片(主分片或副本)。當您重新啟動叢集時,由於某種原因,你只有五個節點線上。這五個節點將彼此通訊,選擇一個master並形成一個叢集。他們注意到資料不再均勻分佈,因為叢集中缺少五個節點,並且立即開始在彼此之間複製新的碎片。一段時間之後,其他五個節點開啟並加入群集。這些節點看到它們的資料被複制到其他節點,因此它們刪除它們的本地資料(因為它現在是冗餘的,並且可能已過時)。然後叢集開始重新平衡,因為叢集大小剛剛從五到十。在整個過程中,您的節點正在顛簸磁碟和網路,移動資料。對於具有TB級資料的大型叢集,這種無用的資料混洗可能需要很長時間。如果所有節點只是等待叢集聯機,所有資料都將是本地的,則不需要移動。
現在我們有一些設定,
1、首先設定gateway.recover_after_nodes: 8 ,這將阻止Elasticsearch在至少存在8個(資料或主節點)節點之前開始恢復,這意味著叢集少於8個節點時不可操作。
2、其次我們告訴Elasticsearch叢集中應該有多少個節點gateway.expected_nodes: 10,以及我們要等待所有這些節點多長時間gateway.recover_after_time: 5m。
這些設定之後,這意味著Elasticsearch將執行以下操作:
1、等待8個節點啟動
2、5分鐘後或十個節點加入群集後開始恢復,兩者策略滿足其一即可。
這三個設定允許您避免在群集重新啟動時可能發生的過多分片交換。 它可以字面上使恢復需要幾秒鐘而不是幾個小時。

比起multicast更傾向於unicast

Elasticsearch預設使用unicast discovery,以防止節點意外加入叢集。
雖然multicast仍然作為外掛提供,但不應在生產中使用。 最後一件事是讓節點偶然加入您的生產網路,只是因為他們收到了錯誤的組播ping。 multicast本身沒有什麼問題,但是會導致愚蠢的問題,並可能有點脆弱(例如,網路工程師在瞎搞網路並且沒有告訴你,可能會突然導致多有的節點不能再找到彼此)。
要使用單播,請向Elasticsearch提供應嘗試聯絡的節點的列表。 當節點聯絡單播列表的成員時,它接收列出叢集中所有節點的完整叢集狀態。 然後它聯絡主機並加入群集。
這意味著您的單播列表不需要包括叢集中的所有節點。 它只需要足夠的節點,一個新的節點可以找到有人談話。
如果你使用專用的主人,只需列出你的3個專用的master。 設定如下:

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