提升ES的寫入速度可以從以下幾方面入手:
- 加大 translog flush ,可以降低 iops,writeblock
- 加大 index refresh 間隔, 除了降低 io, 也降低了 segment merge 頻率
- 調(diào)整 bulk 線程池和隊列
- 優(yōu)化磁盤間的任務(wù)均勻情況,將 shard 盡量均勻分布到物理主機的各磁盤
- 優(yōu)化節(jié)點間的任務(wù)分布,將任務(wù)盡量均勻的發(fā)到各節(jié)點
- 優(yōu)化 lucene 層建立索引的過程,目的是降低 CPU 占用率及 IO
translog flush 間隔調(diào)整
默認設(shè)置下,translog 的持久化策略為:每個請求都flush,對應(yīng)配置項為:index.translog.durability: request
這會很大程度影響 es 寫入速度,但寫操作確很可靠,不會丟失數(shù)據(jù)。如果可以接受一定幾率的數(shù)據(jù)丟失,可以調(diào)整 translog 持久化策略為周期性和一定大小
index.translog.durability: asyncindex.translog.sync_interval: 120s
index.translog.flush_threshold_size: 1024mb
index.translog.flush_threshold_period: 120m
索引刷新間隔調(diào)整: refresh_interval
默認情況下,索引的refresh_interval為1秒,意味著數(shù)據(jù)寫入1秒后就可以被搜索到。
每次索引的 refresh 會產(chǎn)生一個新的 lucene 段,這會導致頻繁的 segment merge 行為,如果不需要這么高的搜索實時性,可以降低索引refresh周期,如:
index.refresh_interval: 120s
磁盤間的任務(wù)均衡
如果部署方案是為 path.data 配置多個路徑來使用多塊磁盤, es 在分配 shard 時,落到各磁盤上的shard可能并不均勻,這種不均勻可能會導致某些磁盤繁忙,利用率達到100%,這種不均勻達到一定程度可能會對寫入性能產(chǎn)生負面影響。
es 在處理多路徑時,優(yōu)先將shard分配到可用空間百分比最多的磁盤,因此短時間內(nèi)創(chuàng)建的 shard 可能被集中分配到這個磁盤,即使可用空間是99%和98%的差別。
es 增加了兩種策略
- 簡單輪詢:系統(tǒng)初始階段,簡單輪詢的效果是最均勻的
- 基于可用空間的動態(tài)加權(quán)輪詢:以可用空間作為權(quán)重,在磁盤之間加權(quán)輪詢
節(jié)點間的任務(wù)均衡
為了在節(jié)點間任務(wù)盡量均衡,數(shù)據(jù)寫入客戶端應(yīng)該把bulk請求輪詢發(fā)送到各個節(jié)點,當使用java api 或者rest api 的bulk接口發(fā)送數(shù)據(jù)時,客戶端將會輪詢的發(fā)送的集群節(jié)點。
當client.transport.sniff為true,列表為所有數(shù)據(jù)節(jié)點;否則,列表為初始化客戶端對象時添加進去的節(jié)點。
觀察bulk 請求在不同節(jié)點上的處理情況,通過 cat 接口觀察 bulk 線程池和隊列情況,是否存在不均:_cat/thread_pool
索引過程調(diào)整和優(yōu)化
- 自動生成 doc ID
分析 es 寫入流程可以看到,寫入 doc 時如果是外部指定了 id,es 會先嘗試讀取原來doc的版本號, 判斷是否需要更新,使用自動生成 doc id 可以避免這個環(huán)節(jié).
- 調(diào)整字段 Mappings
字段的 index 屬性設(shè)置為: not_analyzed,或者 no。
對字段不分詞,或者不索引,可以節(jié)省很多運算,降低 CPU 占用。尤其是 binary 類型,默認情況下占用 CPU 非常高,而這種類型根本不需要進行分詞做索引。
單個 doc 在建立索引時的運算復雜度,最大的因素不在于 doc 的字節(jié)數(shù)或者說某個字段 value 的長度,而是字段的數(shù)量。例如在滿負載的寫入壓力測試中,mapping 相同的情況下,一個有10個字段,200字節(jié)的 doc, 通過增加某些字段 value 的長度到500字節(jié),寫入 es 時速度下降很少,而如果字段數(shù)增加到20,即使整個 doc 字節(jié)數(shù)沒增加多少,寫入速度也會降低一倍。
- 使用不同的分析器:analyzer
不同的分析器在索引過程中運算復雜度也有較大的差異。
調(diào)整_source 字段
_source 字段用于存儲 doc 原始數(shù)據(jù),對于部分不需要存儲的字段,可以通過 includes excludes 來過濾,這樣可以降低 io 的壓力。禁用 _all 字段
_all 字段默認是開啟的,其中包含所有字段分詞后的關(guān)鍵詞,作用是可以在搜索的時候不指定特定字段,從所有字段中檢索。如果你不需要這個特性,可以禁用_all,可以小幅的降低CPU 壓力,對速度影響并不明顯。對于 Analyzed 的字段禁用 Norms
Norms 用于在搜索時計算 doc 的評分,如果不需要評分,可以禁用:"title": {"type": "string","norms": {"enabled": false}}index_options 設(shè)置
index_options 用于控制在建立倒排索引過程中,哪些內(nèi)容會被添加到倒排,例如 doc數(shù)量,詞頻,positions,offsets等信息。
優(yōu)化這些設(shè)置可以一定程度節(jié)省 CPU