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 |
|
這是影響 es 寫入速度的最大因素.但是只有這樣,寫操作才有可能是可靠的,原因參考寫入流程.
如果系統可以接受一定幾率的數據丟失,調整 translog 持久化策略為周期性和一定大小的時候 flush:
|
1 |
|
索引刷新間隔調整: refresh_interval
refresh_interval
默認情況下索引的refresh_interval為1秒,這意味著數據寫1秒后就可以被搜索到,每次索引的 refresh 會產生一個新的 lucene 段,這會導致頻繁的 segment merge 行為,如果你不需要這么高的搜索實時性,應該降低索引refresh 周期,如:
|
1 |
|
segment merge
segment merge 操作對系統 CPU 和 IO 占用都比較高,從es 2.0開始,merge 行為不再由 es 控制,而是轉由 lucene 控制,因此以下配置已被刪除:
|
1 |
|
改為以下調整開關:
|
1 |
|
最大線程數的默認值為:
|
1 |
|
是一個比較理想的值,如果你只有一塊硬盤并且非 SSD, 應該把他設置為1,因為在旋轉存儲介質上并發寫,由于尋址的原因,不會提升,只會降低寫入速度.
merge 策略有三種:
tiered
log_byete_size
log_doc
默認情況下:
|
1 |
|
索引創建時合并策略就已確定,不能更改,但是可以動態更新策略參數,一般情況下,不需要調整.如果堆棧經常有很多 merge, 可以嘗試調整以下配置:
|
1 |
|
該屬性用于阻止segment 的頻繁flush, 小于此值將考慮優先合并,默認為2M,可考慮適當降低此值
|
1 |
|
該屬性指定了每層分段的數量,取值約小最終segment 越少,因此需要 merge 的操作更多,可以考慮適當增加此值.默認為10,他應該大于等于 index.merge.policy.max_merge_at_once
|
1 |
|
指定了單個 segment 的最大容量,默認為5GB,可以考慮適當降低此值
Indexing Buffer
indexing buffer在為 doc 建立索引時使用,當緩沖滿時會刷入磁盤,生成一個新的 segment, 這是除refresh_interval外另外一個刷新索引,生成新 segment 的機會. 每個 shard 有自己的 indexing buffer,下面的關于這個 buffer 大小的配置需要除以這個節點上所有的 shard 數量
|
1 |
|
默認為整個堆空間的10%
|
1 |
|
默認48mb
|
1 |
|
默認無限制
在大量的索引操作時,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 |
|
索引過程調整和優化
自動生成 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 |
|
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 调优之 写入速度优化到极限的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何构建高效可信的持续交付能力,华为云有
- 下一篇: 计算机组成原理7-CISC和RISC、G