您好,登錄后才能下訂單哦!
這篇文章主要介紹“ElasticSearch集群如何調優”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“ElasticSearch集群如何調優”文章能幫助大家解決問題。
系統層面的調優
系統層面的調優主要是內存的設定與避免交換內存。ES 安裝后默認設置的堆內存是 1GB,這很明顯是不夠的,那么接下來就會有一個問題出現:我們要設置多少內存給 ES 呢?
其實這是要看我們集群節點的內存大小,還取決于我們是否在服務器節點上還要部署其他服務。
如果內存相對很大,如 64G 及以上,并且我們不在 ES 集群上部署其他服務,那么我建議 ES 內存可以設置為 31G-32G,因為這里有一個 32G 性能瓶頸問題。
直白的說就是即使你給了 ES 集群大于 32G 的內存,其性能也不一定會更加優良,甚至會不如設置為 31G-32G 時候的性能。
以我調優的集群為例,我所調優的服務器節點內存為 64G,服務器節點上也基本不跑其他服務,所以我把 ES 集群內存大小設置為了 31G,以充分發揮集群性能。
設置 ES 集群內存的時候,還有一點就是確保堆內存最小值(Xms)與***值(Xmx)的大小是相同的,防止程序在運行時改變堆內存大小,這是一個很耗系統資源的過程。
還有一點就是避免交換內存,可以在配置文件中對內存進行鎖定,以避免交換內存(也可以在操作系統層面進行關閉內存交換)。
對應的參數:
bootstrap.mlockall: true
分片與副本
分片 (shard)
ES 是一個分布式的搜索引擎, 索引通常都會分解成不同部分, 分布在不同節點的部分數據就是分片。
ES 自動管理和組織分片, 并在必要的時候對分片數據進行再平衡分配, 所以用戶基本上不用擔心分片的處理細節。創建索引時默認的分片數為 5 個,并且一旦創建不能更改。
副本 (replica)
ES 默認創建一份副本,就是說在 5 個主分片的基礎上,每個主分片都相應的有一個副本分片。
額外的副本有利有弊,有副本可以有更強的故障恢復能力,但也占了相應副本倍數的磁盤空間。
那我們在創建索引的時候,應該創建多少個分片與副本數呢?對于副本數,比較好確定,可以根據我們集群節點的多少與我們的存儲空間決定。
我們的集群服務器多,并且有足夠大多存儲空間,可以多設置副本數,一般是 1-3 個副本數,如果集群服務器相對較少并且存儲空間沒有那么寬松,則可以只設定一份副本以保證容災(副本數可以動態調整)。
對于分片數,是比較難確定的,因為一個索引分片數一旦確定,就不能更改。
所以我們在創建索引前,要充分的考慮到,以后我們創建的索引所存儲的數據量,否則創建了不合適的分片數,會對我們的性能造成很大的影響。
對于分片數的大小,業界一致認為分片數的多少與內存掛鉤,認為 1GB 堆內存對應 20-25 個分片,而一個分片的大小不要超過 50G,這樣的配置有助于集群的健康。
但是我個人認為這樣的配置方法過于死板,我個人在調優 ES 集群的過程中,根據總數據量的大小,設定了相應的分片,保證每一個分片的大小沒有超過 50G(大概在 40G 左右),但是相比之前的分片數查詢起來,效果并不明顯。
之后又嘗試了增加分片數,發現分片數增多之后,查詢速度有了明顯的提升,每一個分片的數據量控制在 10G 左右。
查詢大量小分片使得每個分片處理數據速度更快了,那是不是分片數越多,我們的查詢就越快,ES 性能就越好呢?
其實也不是,因為在查詢過程中,有一個分片合并的過程,如果分片數不斷的增加,合并的時間則會增加。
而且隨著更多的任務需要按順序排隊和處理,更多的小分片不一定要比查詢較小數量的更大的分片更快。如果有多個并發查詢,則有很多小碎片也會降低查詢吞吐量。
如果現在你的場景是分片數不合適了,但是又不知道如何調整,那么有一個好的解決方法就是按照時間創建索引,然后進行通配查詢。
如果每天的數據量很大,則可以按天創建索引,如果是一個月積累起來導致數據量很大,則可以一個月創建一個索引。
如果要對現有索引進行重新分片,則需要重建索引,我會在文章的***總結重建索引的過程。
參數調優
下面我會介紹一些 ES 關鍵參數的調優。有很多場景是,我們的 ES 集群占用了多大的 CPU 使用率,該如何調節呢?
CPU 使用率高,有可能是寫入導致的,也有可能是查詢導致的,那要怎么查看呢?
可以先通過 GET _nodes/{node}/hot_threads 查看線程棧,查看是哪個線程占用 CPU 高:
如果是 elasticsearch[{node}][search][T#10] 則是查詢導致的。
如果是 elasticsearch[{node}][bulk][T#1] 則是數據寫入導致的。
我在實際調優中,CPU 使用率很高,如果不是 SSD,建議把 index.merge.scheduler.max_thread_count: 1 索引 merge ***線程數設置為 1 個,該參數可以有效調節寫入的性能。
因為在存儲介質上并發寫,由于尋址的原因,寫入性能不會提升,只會降低。
還有幾個重要參數可以進行設置,各位同學可以視自己的集群情況與數據情況而定。
index.refresh_interval:這個參數的意思是數據寫入后幾秒可以被搜索到,默認是 1s。
每次索引的 refresh 會產生一個新的 lucene 段, 這會導致頻繁的合并行為,如果業務需求對實時性要求沒那么高,可以將此參數調大,實際調優告訴我,該參數確實很給力,CPU 使用率直線下降。
indices.memory.index_buffer_size:如果我們要進行非常重的高并發寫入操作,那么***將 indices.memory.index_buffer_size 調大一些。
index buffer 的大小是所有的 shard 公用的,一般建議(看的大牛博客),對于每個 shard 來說,最多給 512mb,因為再大性能就沒什么提升了。
ES 會將這個設置作為每個 shard 共享的 index buffer,那些特別活躍的 shard 會更多的使用這個 buffer。默認這個參數的值是 10%,也就是 jvm heap 的 10%。
translog:ES 為了保證數據不丟失,每次 index、bulk、delete、update 完成的時候,一定會觸發刷新 translog 到磁盤上。
在提高數據安全性的同時當然也降低了一點性能。如果你不在意這點可能性,還是希望性能優先,可以設置如下參數:
"index.translog": { "sync_interval": "120s", --sync間隔調高 "durability": "async", -– 異步更新 "flush_threshold_size":"1g" --log文件大小 }
這樣設定的意思是開啟異步寫入磁盤,并設定寫入的時間間隔與大小,有助于寫入性能的提升。
還有一些超時參數的設置:
discovery.zen.ping_timeout 判斷 master 選舉過程中,發現其他 node 存活的超時設置。
discovery.zen.fd.ping_interval 節點被 ping 的頻率,檢測節點是否存活。
discovery.zen.fd.ping_timeout 節點存活響應的時間,默認為 30s,如果網絡可能存在隱患,可以適當調大。
discovery.zen.fd.ping_retries ping 失敗/超時多少導致節點被視為失敗,默認為 3。
其他建議
還有一些零碎的優化建議如下:
插入索引自動生成 id:當寫入端使用特定的 id 將數據寫入 ES 時,ES 會檢查對應的索引下是否存在相同的 id。
這個操作會隨著文檔數量的增加使消耗越來越大,所以如果業務上沒有硬性需求,建議使用 ES 自動生成的 id,加快寫入速率。
避免稀疏索引:索引稀疏之后,會導致索引文件增大。ES 的 keyword,數組類型采用 doc_values 結構。
即使字段是空值,每個文檔也會占用一定的空間,所以稀疏索引會造成磁盤增大,導致查詢和寫入效率降低。
我的調優
下面說一說我的調優:主要是重建索引,更改了現有索引的分片數量,經過不斷的測試,找到了一個***的分片數量。
重建索引的時間是漫長的,在此期間,又對 ES 的寫入進行了相應的調優,使 CPU 使用率降低下來。
附上我的調優參數:
index.merge.scheduler.max_thread_count:1 # 索引 merge ***線程數 indices.memory.index_buffer_size:30% # 內存 index.translog.durability:async # 這個可以異步寫硬盤,增大寫的速度 index.translog.sync_interval:120s #translog 間隔時間 discovery.zen.ping_timeout:120s # 心跳超時時間 discovery.zen.fd.ping_interval:120s # 節點檢測時間 discovery.zen.fd.ping_timeout:120s #ping 超時時間 discovery.zen.fd.ping_retries:6 # 心跳重試次數 thread_pool.bulk.size:20 # 寫入線程個數 由于我們查詢線程都是在代碼里設定好的,我這里只調節了寫入的線程數 thread_pool.bulk.queue_size:1000 # 寫入線程隊列大小 index.refresh_interval:300s #index 刷新間隔復制代碼
關于重建索引
在重建索引之前,首先要考慮一下重建索引的必要性,因為重建索引是非常耗時的。
ES 的 reindex api 不會去嘗試設置目標索引,不會復制源索引的設置,所以我們應該在運行_reindex 操作之前設置目標索引,包括設置映射(mapping),分片,副本等。
***步,和創建普通索引一樣創建新索引
當數據量很大的時候,需要設置刷新時間間隔,把 refresh_intervals 設置為 -1,即不刷新。
number_of_replicas 副本數設置為 0(因為副本數可以動態調整,這樣有助于提升速度)。
{ "settings": { "number_of_shards": "50", "number_of_replicas": "0", "index": { "refresh_interval": "-1" } } "mappings": { } }
第二步,調用 reindex 接口
建議加上 wait_for_completion=false 的參數條件,這樣 reindex 將直接返回 taskId。
POST _reindex?wait_for_completion=false { "source": { "index": "old_index", //原有索引 "size": 5000 //一個批次處理的數據量 }, "dest": { "index": "new_index", //目標索引 } }
第三步:等待
可以通過 GET _tasks?detailed=true&actions=*reindex 來查詢重建的進度。如果要取消 task 則調用_tasks/node_id:task_id/_cancel。
第四步:刪除舊索引,釋放磁盤空間
更多細節可以查看 ES 官網的 reindex api。那么有的同學可能會問,如果我此刻 ES 是實時寫入的,那咋辦呀?
這個時候,我們就要重建索引的時候,在參數里加上上一次重建索引的時間戳。
直白的說就是,比如我們的數據是 100G,這時候我們重建索引了,但是這個 100G 在增加,那么我們重建索引的時候,需要記錄好重建索引的時間戳。
記錄時間戳的目的是下一次重建索引跑任務的時候不用全部重建,只需要在此時間戳之后的重建就可以,如此迭代,直到新老索引數據量基本一致,把數據流向切換到新索引的名字。
POST /_reindex { "conflicts": "proceed", //意思是沖突以舊索引為準,直接跳過沖突,否則會拋出異常,停止task "source": { "index": "old_index" //舊索引 "query": { "constant_score" : { "filter" : { "range" : { "data_update_time" : { "gte" : 123456789 //reindex開始時刻前的毫秒時間戳 } } } } } }, "dest": { "index": "new_index", //新索引 "version_type": "external" //以舊索引的數據為準 } }
關于“ElasticSearch集群如何調優”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。