[Toc]
1、bulk的執(zhí)行過(guò)程
一次bulk請(qǐng)求可能包含了多個(gè)增刪改document的操作内狸,因此bulk的每個(gè)操作都可能要轉(zhuǎn)發(fā)到不同的es node的primary shard去執(zhí)行飒硅,這個(gè)過(guò)程就包含了json數(shù)據(jù)的傳輸束析。
2堡距、假如采用比較良好的json數(shù)組格式
假如使用比較良好的json數(shù)組格式趾断,會(huì)是這個(gè)樣子
POST /_bulk
{ "update": { "_index": "test_index", "_type": "test_type", "_id": "1", "_retry_on_conflict" : 3} }
{
"doc": {
"test_field": "update test"
}
}
這樣看起來(lái)是不是清晰明了绍申?但es是不支持的噩咪。因?yàn)榧偃鏴s支持的話,es需要對(duì)json數(shù)組進(jìn)行額外處理极阅,整個(gè)_bulk流程是下面這樣的
(1) 將良好的json數(shù)組格式解析為JSONArray對(duì)象胃碾,這個(gè)時(shí)候,整個(gè)json就會(huì)在內(nèi)存中出現(xiàn)一份一模一樣的拷貝筋搏,一份是json文本仆百,一份是JSONArray對(duì)象
(2) 解析出json數(shù)組里的每個(gè)json(也就是document)
(3) 對(duì)每個(gè)請(qǐng)求的document進(jìn)行路由
(4) 為路由到同一個(gè)shard上的多個(gè)請(qǐng)求,創(chuàng)建一個(gè)請(qǐng)求數(shù)組
(5) 將這個(gè)請(qǐng)求數(shù)組序列化
(6) 將序列化后的請(qǐng)求數(shù)組發(fā)送到對(duì)應(yīng)的節(jié)點(diǎn)上去
之前提到過(guò)bulk size最佳大小的問(wèn)題奔脐,一般建議在幾千條或者10MB左右俄周。所以說(shuō)可怕的事情來(lái)了,假如有100個(gè)bulk請(qǐng)求發(fā)送到一個(gè)節(jié)點(diǎn)上去髓迎,然后每個(gè)請(qǐng)求是10MB峦朗,100個(gè)請(qǐng)求就是1000M=1G,然后每個(gè)請(qǐng)求的json都copy一份為JSONArray對(duì)象竖般,此時(shí)內(nèi)存占用就會(huì)翻倍甚垦,共占用2G內(nèi)存,甚至不止,因?yàn)榕蒍SONArray之后艰亮,還可能會(huì)搞一些其它的數(shù)據(jù)結(jié)構(gòu)闭翩,就會(huì)占用2G+的內(nèi)存。
占用更多的內(nèi)存可能就會(huì)積壓內(nèi)存迄埃,影響其它請(qǐng)求的內(nèi)存使用量疗韵,比如說(shuō)最重要的搜索請(qǐng)求、搜索請(qǐng)求等等侄非,此時(shí)就可能導(dǎo)致其它請(qǐng)求的性能急速下降蕉汪。
另外,占用內(nèi)存更多逞怨,也會(huì)導(dǎo)致java虛擬機(jī)的垃圾回收次數(shù)更頻繁者疤,每次要回收的垃圾對(duì)象更多,耗費(fèi)時(shí)間更多叠赦,導(dǎo)致es的java虛擬機(jī)阻塞工作線程的時(shí)間更多
3驹马、es支持的json格式
bulk的格式要求為一條數(shù)據(jù)的json要放在一行
POST /_bulk
{ "update": { "_index": "test_index", "_type": "test_type", "_id": "1", "_retry_on_conflict" : 3} }
{ "doc" : {"test_field" : "update test"} }
這樣做有什么好處呢?我們來(lái)看下整個(gè)_bulk流程
(1) 不用將其轉(zhuǎn)換為json對(duì)象除秀,不會(huì)出現(xiàn)內(nèi)存中相同數(shù)據(jù)的拷貝糯累,直接按照換行符切割json
(2) 對(duì)每?jī)蓚€(gè)一組的json,讀取meta册踩,進(jìn)行document路由
(3) 直接將對(duì)應(yīng)的json發(fā)送到node上去
其最大優(yōu)勢(shì)在于泳姐,不需要講json數(shù)組解析為一個(gè)JSONArray對(duì)象,形成一份大數(shù)據(jù)的拷貝暂吉,浪費(fèi)內(nèi)存空間胖秒,盡可能地保證性能