ES寫入性能優化

背景: 有1億多的用戶畫像中數倉須要導入ES。大多數字段都是sql統計數據,沒法區分哪些發生了變化,因此不能增量更新。只能天天全量刷數據。在刷數據的過程當中出現了更新緩慢、內存問題。因而作了一些寫入優化。java


解決方案

1. 讀數據

首先要從數倉讀取出數據到內存。而後再組裝對象去ES刷數據字段比較多並且都須要查詢。嘗試了一下,即便limit 10,也須要耗時2分鐘。因此第一步導數據不能直接查詢。採用的是數倉到分佈式文件系統分片存儲。這一步已經有現成工具。1億數據導入到分片耗時3分鐘左右sql

2.組裝數據

將分片的數據讀到java內存中。再構造請求參數刷ES多線程

`問題:1.刷數據ES報413錯誤。ES建議每次bulk5~15M數據,這裏我每次批量提交5000條,bulk的時候發生的413 requets too large錯誤,google了一下,說是索引的時候段合併內存不夠。因而調整indices.breaker.fielddata.limit爲60%,增大堆內存,結果沒什麼用;也有說要調整 client_max_body_size 的,可是咱們的es是雲服務,無法改配置參數最終加大es的內存爲16G,再也不報這個錯誤。分佈式

2.以前寫業務代碼數據量通常不是很大,採用的是一次性把數據讀取到內存中。再作業務處理。可是此次在數據塞到一半的數據,先是系統響應變慢了,後來測試環境的系統掛了。經過過命令排查,發現List對象佔用了不少空間。因而複查代碼。發現是for循環一直往list填對象致使的內存泄露。因而限制了單個文件大小爲20M,一個文件一個文件地處理。 `工具

3.提升es索引效率

剛開始刷數據預計須要20個小時。今天的數據若是明天才更新完,意義不大。因而想辦法提升索引效率。網上都說"refresh_interval": "-1";調整number_of_replicas=0。我調整告終果沒什麼變化。因而採用多線程刷數據性能

問題:1.一開始使用size爲20的無界隊列,致使耗盡資源,任務線程佔用的內存佔用了80+%的內存,其餘任務可能被拖垮。後來線程的核心線程數和最大線程數統一設置爲10。並採用future模式,一個任務完成後再去添加其餘任務。解決了線程耗盡資源和內存的問題。測試

用htop查看刷數據機器的性能

能夠看到開啓的10個線程佔用42%內存。主線程cpu偶爾接近100%,這不是io密集型嗎?怎麼會耗cpu。cpu變高多是複雜的技術或者死循環。這裏循環每次讀取量有50000條,而且組裝對象的邏輯。並且有10個線程,猜測多是這個緣由。優化

ES的索引速率 google

成果

最後原來須要20小時才能完成的刷數據任務,只耗時約100分鐘。固然中間遇到的坑不止這些線程

相關文章
相關標籤/搜索