1、tranlog flush 間隔調整
默認設置下,每個請求都flush,這是影響es寫入速度的最大因素,需要調整translog持久化策略為周期性和一定大小的時候flush,例如:
index.translog.durability: async
設置為async表示translog的刷盤策略按sync_interval配置指定的時間周期進行。
index.translog.sync_interval:120s
加大translog刷盤間隔時間。默認5s,不低於100ms.
index.translog.flush_threshold_size: 1024mb
超過這個大小導致refresh,默認512MB
2、並發執行bulk請求
單線程發送bulk請求是無法最大化es集群寫入的吞吐量的。如果要利用集群的所有資源,就需要使用多線程並發將數據bulk寫入集群中。為了更好的利用集群的資源,這樣多線程並發寫入,可以減少每次底層磁盤fsync的次數和開銷。首先對單個es節點的單個shard做壓測,比如說,先是2個線程,然后是4個線程,然后是8個線程,16個,每次線程數量倍增。一旦發現es返回了TOO_MANY_REQUESTS的錯誤,JavaClient也就是EsRejectedExecutionException。此時那么就說明es是說已經到了一個並發寫入的最大瓶頸了,此時我們就知道最多只能支撐這么高的並發寫入了。
3、增加refresh interval
默認的refresh間隔是1s,用index.refresh_interval參數可以設置,這樣會其強迫es每秒中都將內存中的數據寫入磁盤中,創建一個新的segment file。正是這個間隔,讓我們每次寫入數據后,1s以后才能看到。但是如果我們將這個間隔調大,比如30s,可以接受寫入的數據30s后才看到,那么我們就可以獲取更大的寫入吞吐量,因為30s內都是寫內存的,每隔30s才會創建一個segment file。
4、磁盤間的任務均衡
- 簡單輪詢:在系統初始階段,簡單輪詢的效果是最均勻的。
- 基於可用空間的動態加權輪詢:以可用空間作為權重,在磁盤之家加權輪詢。
5、節點間的任務均衡
為了節點間的任務盡量均衡,數據寫入客戶端應該把bulk請求輪詢發送到各個節點。
6、調整字段Mappings
-
減少字段數量,不需要建立索引的字段,不寫入ES
-
將不需要建立索引的字段index屬性設置not_analyed或no
-
減少字段內容長度
-
使用不同的分析器
7、使用自動生成的id
如果我們要手動給es document設置一個id,那么es需要每次都去確認一下那個id是否存在,這個過程是比較耗費時間的。如果我們使用自動生成的id,那么es就可以跳過這個步驟,寫入性能會更好。對於你的業務中的表id,可以作為es document的一個field。
8、段合並優化
merge策略默認用的tiered,但是可以對策略的參數進行一些調整。如果堆棧經常有很多merge,則可以嘗試調整以下策略配置:
index.merge.policy.segments_per_tier
取值越小則最終segment越少,因此需要merge的操作更多,可以考慮增加此值,默認為10,應該大於等於index.merge.policy.max_merge_at_once
。
9、indexing buffer
如果我們要進行非常重的高並發寫入操作,那么最好將index buffer調大一些,這和可用堆內存、單節點上的shard數量相關,indices.memory.index_buffer_size,這個可以調節大一些,設置的這個index buffer大小,是所有的shard公用的,但是如果除以shard數量以后,算出來平均每個shard可以使用的內存大小,一般建議,但是對於每個shard來說,最多給512mb,因為再大性能就沒什么提升了。es會將這個設置作為每個shard共享的index buffer,那些特別活躍的shard會更多的使用這個buffer。默認這個參數的值是10%,也就是jvm heap的10%,如果我們給jvmheap分配10gb內存,那么這個index buffer就有1gb,對於兩個shard共享來說,是足夠的了。
10、禁用_all字段
禁止_all字段可以明顯降低對CPU和I/O的壓力。