前兩天業(yè)務方突然找到我說當天索引ES查詢很慢,原來毫秒級的查詢現(xiàn)在竟然要20s,讓我處理下。我看了下索引大小,原來是1分片6g左右,今天突然就變成了1分片32g。然后我就一臉硬氣的告訴他,你們業(yè)務膨脹了5倍,為什么不和平臺這邊溝通,一分片30多g肯定慢。然后業(yè)務一臉懵逼的查了一通,告訴我業(yè)務大小沒變化。業(yè)務方說數(shù)據(jù)大小沒變,我這邊logtash也沒動過,難道是推送kafka的時候,多推送了幾次?(我自己沒做改動,不可能有問題的好嗎?肯定是別人有問題。。。。。)我讓負責kakfa的同學幫忙查了一下,他告訴我kafka接收到的數(shù)據(jù)和往常一樣,沒變化。業(yè)務數(shù)據(jù)量沒變,kafka接收到的數(shù)據(jù)量也沒變,那只能是logtash的問題。但logstash我也沒改,為什么今天就突然變大了呢?
然后我試著查看其他業(yè)務當天的索引,發(fā)現(xiàn)也特別慢。查看segments發(fā)現(xiàn),一個一分片0副本的索引segments竟然有1400多。這肯定慢,從一個文件中查詢與從1400個文件這個性能差的不是一點半點。
直覺告訴我,segments沒合并和logtash重復消費兩者肯定有關系。
logtash重復消費
關于logstash重復消費問題,這篇文章http://www.itdecent.cn/p/6492b762c171介紹了原因。kafka的consumer消費數(shù)據(jù)時首先會從broker里讀取一批消息數(shù)據(jù)進行處理,處理完成后再提交offset。如果這一批消息處理時間過長,在session.timeout.ms時間內沒有處理完成,自動提交offset失敗,然后kafka會重新分配partition給消費者,消費者又重新消費之前的一批數(shù)據(jù),又出現(xiàn)了消費超時,所以會造成死循環(huán),一直消費相同的數(shù)據(jù)。同時也給出了解決方案:將max_poll_records 調小,將session_timeout_ms調大即可。
問題解決流程:
1)首次嘗試,將session_timeout_ms調整為和auto_commit_interval_ms默認值5s一樣。觀察了一段時間發(fā)現(xiàn)沒什么效果。當時在想為啥一批數(shù)據(jù)需要處理這么久?
2)調整session_timeout_ms沒什么效果,那就只能減少每一批數(shù)據(jù)的大小了。logstash的配置中,我沒有配置每批的數(shù)據(jù)條數(shù)max_poll_records ,而配置了每批數(shù)據(jù)大小max_partition_fetch_bytes。將其減少為原來的一半,logstash不在重復消費kafka,終于恢復正常了。
當天索引的segments沒合并
查了一圈資料也沒找到segmetns沒合并的原因。ES可以通過_forcemerge暴力合并,但對正在讀寫的索引卻不建議這么做。因為merge進程會阻塞所有的寫請求,知道m(xù)erge結束。官網(wǎng)的原文是這么說的:
The force merge API allows to force merging of one or more indices through an API. The merge relates to the number of segments a Lucene index holds within each shard. The force merge operation allows to reduce the number of segments by merging them.
This call will block until the merge is complete. If the http connection is lost, the request will continue in the background, and any new requests will block until the previous force merge is complete.
forcemerge肯定是不行的,我們知道ES后臺有segments合并的線程,難道是系統(tǒng)的合并線程掛了,沒重啟起來?
問題解決流程:
1)重啟大發(fā)好,先重啟一把試試。重啟恢復正常,過了半個小時后我查看業(yè)務當天的segments發(fā)現(xiàn)果然少了,由原來的1400多變?yōu)榱?00多個。果然還是重啟大發(fā)好。我告訴業(yè)務已經(jīng)弄好了,讓他多觀察下。
2)第二天業(yè)務方又找到我說很卡,我查看segments發(fā)現(xiàn),segmetns又有400多了(上午),按照這個進度推下去,晚上又會達到1000多。WTF?
又翻了一遍官網(wǎng)關于merge的信息,突然發(fā)現(xiàn)這句話:
A shard in elasticsearch is a Lucene index, and a Lucene index is broken down into segments. Segments are internal storage elements in the index where the index data is stored, and are immutable. Smaller segments are periodically merged into larger segments to keep the index size at bay and to expunge deletes.
The merge process uses auto-throttling to balance the use of hardware resources between merging and other activities like search.
意思就是說合并進程會根據(jù)系統(tǒng)的負載自動在讀寫和merge之間做均衡,如果讀寫壓力非常大,那么merge就有可能會很慢。那沒毛病了,肯定是讀寫壓力大,引起系統(tǒng)降低了merge的頻率。我突然想起來集群中有個業(yè)務變了,由原來的每天200G,變?yōu)槊刻?T。
沒錯就是因為其他業(yè)務突然增長了10倍,使集群寫壓力增大,然后logstash向ES寫數(shù)據(jù)的時候耗費的時間更長,session才會timeout,才會一直重復消費,引起當天索引變大。還是因為集群寫壓力大,然后系統(tǒng)merge操作減少頻率,導致當天索引segments沒合并,查詢特別慢。
加機器就好了。