日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

Elasticsearch 调优之 写入速度优化到极限

發布時間:2023/12/13 综合教程 30 生活家
生活随笔 收集整理的這篇文章主要介紹了 Elasticsearch 调优之 写入速度优化到极限 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


基于版本: 2.x – 5.x

在 es 的默認設置,是綜合考慮數據可靠性,搜索實時性,寫入速度等因素的,當你離開默認設置,追求極致的寫入速度時,很多是以犧牲可靠性和搜索實時性為代價的.有時候,業務上對兩者要求并不高,反而對寫入速度要求很高,例如在我的場景中,要求每秒200w 條的平均寫入速度,每條500字節左右

接下來的優化基于集群正常運行的前提下,如果是集群首次灌入數據,可以將副本數設置為0,寫入完畢再調整回去,這樣副本分片只需要拷貝,節省了索引過程.

綜合來說,提升寫入速度從以下幾方面入手:

加大 translog flush ,目的是降低 iops,writeblock
加大 index refresh間隔, 目的除了降低 io, 更重要的降低了 segment merge 頻率
調整 bulk 線程池和隊列
優化磁盤間的任務均勻情況,將 shard 盡量均勻分布到物理主機的各磁盤
優化節點間的任務分布,將任務盡量均勻的發到各節點
優化 lucene 層建立索引的過程,目的是降低 CPU 占用率及 IO

translog flush 間隔調整


從 es 2.x 開始, 默認設置下,translog 的持久化策略為:每個請求都flush.對應配置項為:

1
2
3


index.translog.durability: request

這是影響 es 寫入速度的最大因素.但是只有這樣,寫操作才有可能是可靠的,原因參考寫入流程.
如果系統可以接受一定幾率的數據丟失,調整 translog 持久化策略為周期性和一定大小的時候 flush:

1
2
3
4
5
6


index.translog.durability: async
index.translog.sync_interval: 120s
index.translog.flush_threshold_size: 1024mb
index.translog.flush_threshold_period: 120m

索引刷新間隔調整: refresh_interval


refresh_interval

默認情況下索引的refresh_interval為1秒,這意味著數據寫1秒后就可以被搜索到,每次索引的 refresh 會產生一個新的 lucene 段,這會導致頻繁的 segment merge 行為,如果你不需要這么高的搜索實時性,應該降低索引refresh 周期,如:

1
2
3


index.refresh_interval: 120s

segment merge

segment merge 操作對系統 CPU 和 IO 占用都比較高,從es 2.0開始,merge 行為不再由 es 控制,而是轉由 lucene 控制,因此以下配置已被刪除:

1
2
3
4
5
6


indices.store.throttle.type
indices.store.throttle.max_bytes_per_sec
index.store.throttle.type
index.store.throttle.max_bytes_per_sec

改為以下調整開關:

1
2
3
4


index.merge.scheduler.max_thread_count
index.merge.policy.*

最大線程數的默認值為:

1
2
3


Math.max(1, Math.min(4, Runtime.getRuntime().availableProcessors() / 2))

是一個比較理想的值,如果你只有一塊硬盤并且非 SSD, 應該把他設置為1,因為在旋轉存儲介質上并發寫,由于尋址的原因,不會提升,只會降低寫入速度.

merge 策略有三種:

tiered
log_byete_size
log_doc

默認情況下:

1
2
3


index.merge.polcy.type: tiered

索引創建時合并策略就已確定,不能更改,但是可以動態更新策略參數,一般情況下,不需要調整.如果堆棧經常有很多 merge, 可以嘗試調整以下配置:

1
2
3


index.merge.policy.floor_segment

該屬性用于阻止segment 的頻繁flush, 小于此值將考慮優先合并,默認為2M,可考慮適當降低此值

1
2
3


index.merge.policy.segments_per_tier

該屬性指定了每層分段的數量,取值約小最終segment 越少,因此需要 merge 的操作更多,可以考慮適當增加此值.默認為10,他應該大于等于 index.merge.policy.max_merge_at_once

1
2
3


index.merge.policy.max_merged_segment

指定了單個 segment 的最大容量,默認為5GB,可以考慮適當降低此值

Indexing Buffer

indexing buffer在為 doc 建立索引時使用,當緩沖滿時會刷入磁盤,生成一個新的 segment, 這是除refresh_interval外另外一個刷新索引,生成新 segment 的機會. 每個 shard 有自己的 indexing buffer,下面的關于這個 buffer 大小的配置需要除以這個節點上所有的 shard 數量

1
2
3


indices.memory.index_buffer_size

默認為整個堆空間的10%

1
2
3


indices.memory.min_index_buffer_size

默認48mb

1
2
3


indices.memory.max_index_buffer_size

默認無限制

在大量的索引操作時,indices.memory.index_buffer_size默認設置可能不夠,這和可用堆內存,單節點上的 shard 數量相關,可以考慮適當增大.

bulk 線程池和隊列大小

建立索引的過程偏計算密集型任務,應該使用固定大小的線程池配置,來不及處理的放入隊列,線程數量配置為 CPU 核心數+1,避免過多的上下文切換.隊列大小可以適當增加.

磁盤間的任務均衡


如果你的部署方案是為path.data 配置多個路徑來使用多塊磁盤, es 在分配 shard 時,落到各磁盤上的 shard 可能并不均勻,這種不均勻可能會導致某些磁盤繁忙,利用率達到100%,這種不均勻達到一定程度可能會對寫入性能產生負面影響.

es 在處理多路徑時,優先將 shard 分配到可用空間百分比最多的磁盤,因此短時間內創建的 shard 可能被集中分配到這個磁盤,即使可用空間是99%和98%的差別.后來 es 在2.x 版本中開始解決這個問題的方式是:預估一下這個 shard 會使用的空間,從磁盤可用空間中減去這部分,直到現在6.x beta 版也是這種處理方式.但是實現也存在一些問題:

從可用空間減去預估大小

這種機制只存在于一次索引創建的過程中,下一次的索引創建,磁盤可用空間并不是上次做完減法以后的結果,這也可以理解,畢竟預估是不準的,一直減下去很快就減沒了.

但是最終的效果是,這種機制并沒有從根本上解決問題,即使沒有完美的解決方案,這種機制的效果也不夠好.

如果單一的機制不能解決所有的場景,至少應該為不同場景準備多種選擇.

為此,我們為 es 增加了兩種策略
簡單輪詢:系統初始階段,簡單輪詢的效果是最均勻的
基于可用空間的動態加權輪詢:以可用空間作為權重,在磁盤之間加權輪詢

節點間的任務均衡


為了在節點間任務盡量均衡,數據寫入客戶端應該把 bulk 請求輪詢發送到各個節點.

當使用 java api ,或者 rest api 的 bulk 接口發送數據時,客戶端將會輪詢的發送的集群節點,節點列表取決于:
client.transport.sniff為 true,(默認為 false),列表為所有數據節點
否則,列表為初始化客戶端對象時添加進去的節點.

java api 的 TransportClient 和 rest api 的 RestClient 都是線程安全的,當寫入程序自己創建線程池控制并發,應該使用同一個 Client 對象.在此建議使用 rest api,兼容性好,只有吞吐量非常大才值得考慮序列化的開銷,顯然搜索并不是高吞吐量的業務.

觀察bulk 請求在不同節點上的處理情況,通過cat 接口觀察 bulk 線程池和隊列情況,是否存在不均:

1
2
3


_cat/thread_pool

索引過程調整和優化


自動生成 doc ID

分析 es 寫入流程可以看到,寫入 doc 時如果是外部指定了 id,es 會先嘗試讀取原來doc的版本號, 判斷是否需要更新,使用自動生成 doc id 可以避免這個環節.

調整字段 Mappings

字段的 index 屬性設置為: not_analyzed,或者 no

對字段不分詞,或者不索引,可以節省很多運算,降低 CPU 占用.尤其是 binary 類型,默認情況下占用 CPU 非常高,而這種類型根本不需要進行分詞做索引.

單個 doc 在建立索引時的運算復雜度,最大的因素 不在于 doc 的字節數或者說某個字段 value 的長度,而是字段的數量. 例如在滿負載的寫入壓力測試中,mapping 相同的情況下,一個有10個字段,200字節的 doc, 通過增加某些字段 value 的長度到500字節,寫入 es 時速度下降很少,而如果字段數增加到20,即使整個 doc 字節數沒增加多少,寫入速度也會降低一倍.

使用不同的分析器:analyzer

不同的分析器在索引過程中運算復雜度也有較大的差異

調整_source 字段

_source 字段用于存儲 doc 原始數據,對于部分不需要存儲的字段,可以通過 includes excludes 來過濾,或者將 _source 禁用,一般用于索引和數據分離

這樣可以降低 io 的壓力,不過實際場景大多數情況不會禁用 _source ,而即使過濾掉某些字段,對于寫入速度的提示效果也不大,滿負荷寫入情況下,基本是CPU 先跑滿了,瓶頸在于 CPU.

禁用 _all 字段

_all 字段默認是開啟的,其中包含所有字段分詞后的關鍵詞,作用是可以在搜索的時候不指定特定字段,從所有字段中檢索.如果你不需要這個特性,可以禁用 _all,可以小幅的降低CPU 壓力,對速度影響并不明顯.

對于 Analyzed 的字段禁用 Norms

Norms 用于在搜索時計算 doc 的評分,如果不需要評分,可以禁用他:

1
2
3


"title": {"type": "string","norms": {"enabled": false}}

index_options 設置

index_options 用于控制在建立倒排索引過程中,哪些內容會被添加到倒排,例如 doc數量,詞頻,positions,offsets等信息,優化這些設置可以一定程度降低索引過程中運算任務,節省 CPU 占用率

不過實際場景中,通常很難確定業務將來會不會用到這些信息,除非一開始方案就明確這樣設計的

方法比結論重要


當面對一個系統性問題的時候,往往是多種因素造成的,在處理集群的寫入性能問題上,先將問題分解,在單臺上分析調整最高能力到某種系統資源達到極限,其中觀察利用率,io block,線程切換,堆棧狀態等,解決局部問題,在此基礎上解決整體問題會容易很多

最后


jvm 參數除了 Xmx,Xms 其他盡量使用默認,一些看起來比較合理的參數實際效果可能適得其反。

共享下我的配置:

template-base
elasticsearch

參考鏈接


https://doc.yonyoucloud.com/doc/mastering-elasticsearch/chapter-3/36_README.html
https://qbox.io/blog/maximize-guide-elasticsearch-indexing-performance-part-1
https://qbox.io/blog/maximize-guide-elasticsearch-indexing-performance-part-2
https://qbox.io/blog/maximize-guide-elasticsearch-indexing-performance-part-3

相關文章:

elasticsearch 一次長時間 FGC 問題分析
elasticsearch 寫流程
elasticsearch 機制和架構

(轉載請注明作者和出處 easyice.cn ,請勿用于任何商業用途)

總結

以上是生活随笔為你收集整理的Elasticsearch 调优之 写入速度优化到极限的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。