bulk Java提交数据,性能优化 – bulk提交 - ELK Stack 中文指南
在 CRUD 章節(jié),我們已經(jīng)知道 ES 的數(shù)據(jù)寫入是如何操作的了。喜歡自己動(dòng)手的讀者可能已經(jīng)迫不及待的自己寫了程序開(kāi)始往 ES 里寫數(shù)據(jù)做測(cè)試。這時(shí)候大家會(huì)發(fā)現(xiàn):程序的運(yùn)行速度非常一般,即使 ES 服務(wù)運(yùn)行在本機(jī),一秒鐘大概也就能寫入幾百條數(shù)據(jù)。
這種速度顯然不是 ES 的極限。事實(shí)上,每條數(shù)據(jù)經(jīng)過(guò)一次完整的 HTTP POST 請(qǐng)求和 ES indexing 是一種極大的性能浪費(fèi),為此,ES 設(shè)計(jì)了批量提交方式。在數(shù)據(jù)讀取方面,叫 mget 接口,在數(shù)據(jù)變更方面,叫 bulk 接口。mget 一般常用于搜索時(shí) ES 節(jié)點(diǎn)之間批量獲取中間結(jié)果集,對(duì)于 Elastic Stack 用戶,更常見(jiàn)到的是 bulk 接口。
bulk 接口采用一種比較簡(jiǎn)樸的數(shù)據(jù)積累格式,示例如下:
# curl -XPOST http://127.0.0.1:9200/_bulk -d'
{ "create" : { "_index" : "test", "_type" : "type1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test", "_type" : "type1" } }
{ "index" : { "_index" : "test", "_type" : "type1", "_id" : "1" } }
{ "field1" : "value2" }
{ "update" : {"_id" : "1", "_type" : "type1", "_index" : "test"} }
{ "doc" : {"field2" : "value2"} }
'
格式是,每條 JSON 數(shù)據(jù)的上面,加一行描述性的元 JSON,指明下一行數(shù)據(jù)的操作類型,歸屬索引信息等。
采用這種格式,而不是一般的 JSON 數(shù)組格式,是因?yàn)榻邮盏?bulk 請(qǐng)求的 ES 節(jié)點(diǎn),就可以不需要做完整的 JSON 數(shù)組解析處理,直接按行處理簡(jiǎn)短的元 JSON,就可以確定下一行數(shù)據(jù) JSON 轉(zhuǎn)發(fā)給哪個(gè)數(shù)據(jù)節(jié)點(diǎn)了。這樣,一個(gè)固定內(nèi)存大小的 network buffer 空間,就可以反復(fù)使用,又節(jié)省了大量 JVM 的 GC。
事實(shí)上,產(chǎn)品級(jí)的 logstash、rsyslog、spark 都是默認(rèn)采用 bulk 接口進(jìn)行數(shù)據(jù)寫入的。對(duì)于打算自己寫程序的讀者,建議采用 Perl 的 Search::Elasticsearch::Bulk 或者 Python 的 elasticsearch.helpers.* 庫(kù)。
bulk size
在配置 bulk 數(shù)據(jù)的時(shí)候,一般需要注意的就是請(qǐng)求體大小(bulk size)。
這里有一點(diǎn)細(xì)節(jié)上的矛盾,我們知道,HTTP 請(qǐng)求,是可以通過(guò) HTTP 狀態(tài)碼 100 Continue 來(lái)持續(xù)發(fā)送數(shù)據(jù)的。但對(duì)于 ES 節(jié)點(diǎn)接收 HTTP 請(qǐng)求體的 Content-Length 來(lái)說(shuō),是按照整個(gè)大小來(lái)計(jì)算的。所以,首先,要確保 bulk 數(shù)據(jù)不要超過(guò) http.max_content_length 設(shè)置。
那么,是不是盡量讓 bulk size 接近這個(gè)數(shù)值呢?當(dāng)然不是。
依然是請(qǐng)求體的問(wèn)題,因?yàn)檎?qǐng)求體需要全部加載到內(nèi)存,而 JVM Heap 一共就那么多(按 31GB 算),過(guò)大的請(qǐng)求體,會(huì)擠占其他線程池的空間,反而導(dǎo)致寫入性能的下降。
再考慮網(wǎng)卡流量,磁盤轉(zhuǎn)速的問(wèn)題,所以一般來(lái)說(shuō),建議 bulk 請(qǐng)求體的大小,在 15MB 左右,通過(guò)實(shí)際測(cè)試?yán)^續(xù)向上探索最合適的設(shè)置。
注意:這里說(shuō)的 15MB 是請(qǐng)求體的字節(jié)數(shù),而不是程序里里設(shè)置的 bulk size。bulk size 一般指數(shù)據(jù)的條目數(shù)。不要忘了,bulk 請(qǐng)求體中,每條數(shù)據(jù)還會(huì)額外帶上一行元 JSON。
以 logstash 默認(rèn)的 bulk_size => 5000 為例,假設(shè)單條數(shù)據(jù)平均大小 200B ,一次 bulk 請(qǐng)求體的大小就是 1.5MB。那么我們可以嘗試 bulk_size => 50000;而如果單條數(shù)據(jù)平均大小是 20KB,一次 bulk 大小就是 100MB,顯然超標(biāo)了,需要嘗試下調(diào)至 bulk_size => 500。
總結(jié)
以上是生活随笔為你收集整理的bulk Java提交数据,性能优化 – bulk提交 - ELK Stack 中文指南的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 一个显示器分两个屏幕_桌面改造计划2.0
- 下一篇: java web 自定义异常_Java