共計 2425 個字符,預計需要花費 7 分鐘才能閱讀完成。
這篇文章給大家分享的是有關如何優化 Elasticsearch 寫入速度的內容。丸趣 TV 小編覺得挺實用的,因此分享給大家做個參考,一起跟隨丸趣 TV 小編過來看看吧。
本次優化的示例版本是 7.9.2。ES 的版本升的是真快,已經完全脫離了 5 的時代了。
1、哪些操作占用資源
要進行優化,需要首先知道 ES 的寫入過程,了解哪些步驟最耗時。
首先,就是副本 (replica) 問題,為了保證起碼的高可用,這里的副本數量設置為 1,是節省不了的。所以,將副本數量設置為 0,只適合數據首次導入的時候。
如上圖,一條數據想要最終落地,是需要經過多個步驟的。這個過程,甚至會有 tranlog 這樣的備份機制。
ES 的底層存儲是 Lucene,包含一系列的反向索引。這樣的索引就成為段(segment)。但記錄不會直接寫入段,而是先寫入一個緩沖區。
當緩沖區滿了,或者在緩沖區呆的夠久,達到了刷新時間(劃重點),會一次性將緩沖區的內容寫進段中。
這也是為什么 refresh_interval 屬性的配置會嚴重的影響性能。如果你不要很高的實時性,不妨將其配置的大一點。
緩沖區默認使用堆空間的 10%,最小值為 48mb(針對于分片的)。如果你的索引多且寫入重,這部分內存的占用是可觀的,可以適當加大。
2、開始優化
數據寫入,主要有三個動作:flush、refresh 和 merge。通過調整它們的行為,即可在性能和數據可靠性之間進行權衡。
flush
從上面的介紹可以看出來,translog 寫入了一份全量的數據,它有點像 MysSQL 中的 binlog,或者 redis 的 aof,用來保證異常情況下的數據安全。
這是因為,我們把數據寫到磁盤后,還要調用 fsync 才能把數據刷到磁盤中,如果不這樣做在系統掉電的時候就會導致數據丟失。
ES 默認每次請求都進行一次 flush,但對于日志來說,這沒有必要,可以將這個過程改為異步的,參數如下:
curl -H Content-Type: application/json -XPUT http://localhost:9200/_all/_settings?preserve_existing=true -d { index.translog.durability : async , index.translog.flush_threshold_size : 512mb , index.translog.sync_interval : 60s }
這可以說是最重要的一步優化了,對性能的影響最大,但在極端情況下會有丟失部分數據的可能。對于日志系統來說,是可以忍受的。
refresh
除了寫 translog,ES 還會將數據寫入到一個緩沖區中。但是注意了! 此時,緩沖區的內容是無法被搜索到的,它還需要寫入到 segment 里面才可以。
這就是 refresh 動作,默認 1 秒。也就是你寫入的數據,大概率 1 秒之后才會被搜索到。
所以 ES 并不是一個實時性的搜索系統,它是一個類實時系統(near-realtime)。
通過 index.refresh_interval 可以修改這個刷新間隔。
對于日志系統來說,當然要把它調大一點啦。xjjdog 這里調整到了 120s,減少了這些落到 segment 的頻率,速度自然會快。
curl -H Content-Type: application/json -XPUT http://localhost:9200/_all/_settings?preserve_existing=true -d { index.refresh_interval : 120s }
merge
merge 其實是 lucene 的機制,它主要是合并小的 segment 塊,生成更大的 segment,來提高檢索的速度。
原因就是 refresh 過程會生成一大堆小 segment 文件,數據刪除也會產生空間碎片。所以 merge,通俗來講就像是碎片整理進程。像 postgresql 等,也有 vaccum 進程在干同樣的事。
顯而易見,這種整理操作,既讓費 I /O,又浪費 CPU。
要命的是,merge 有三種策略。
tiered 默認選項,它能合并大小相似的索引段,并考慮每層允許的索引段的最大個數。
log_byte_size 以字節數的對數為計算單位,選擇多個索引來合并創建新索引。
log_doc 以索引段的文檔數量為計算單位,選擇多個索引來合并創建新索引。
每一種策略都有非常詳細的針對性配置,在此不啰嗦。
由于日志系統并沒有隨機性的刪除操作,所以我們保持默認就可以。
3、微調
新版本對線程池的配置進行了優化,不需要配置復雜的 search、bulk、index 線程池。有需要配置下面幾個就行了:thread_pool.get.size, thread_pool.write.size, thread_pool.listener.size, thread_pool.analyze.size。具體可觀測_cat/thread_pool 接口暴露的數據進行調整。
其實,可以通過配置多塊磁盤的方式,來分散 I / O 的壓力,但容易會造成數據熱點集中在單塊磁盤上。
Lucene 的索引建立過程,非常耗費 CPU,可以減少倒排索引的數量來減少 CPU 的損耗。第一個優化就是減少字段的數量; 第二個優化就是減少索引字段的數量。具體的操作,是將不需要搜索的字段,index 屬性設置為 not_analyzed 或者 no。至于_source 和_all,在實際調試中效果不大,不再贅述。
另外,如果日志是通過 filebeat 或者 logstash 這樣的組件傳導過來的,一般都是開啟了批量模式。通過批量能夠增加性能,但也不宜過大,可根據實際觀測進行設置,一般 1k-1w 之間都是可以的。
感謝各位的閱讀!關于“如何優化 Elasticsearch 寫入速度”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!