跟我學Elasticsearch(16) _bulk api的奇特json格式與底層性能關(guān)系

[Toc]

1、bulk的執(zhí)行過程

一次bulk請求可能包含了多個增刪改document的操作,因此bulk的每個操作都可能要轉(zhuǎn)發(fā)到不同的es node的primary shard去執(zhí)行,這個過程就包含了json數(shù)據(jù)的傳輸。

2、假如采用比較良好的json數(shù)組格式

假如使用比較良好的json數(shù)組格式,會是這個樣子

POST /_bulk
{ "update": { "_index": "test_index", "_type": "test_type", "_id": "1", "_retry_on_conflict" : 3} }
{
    "doc": {
        "test_field": "update test"
    }
}

這樣看起來是不是清晰明了?但es是不支持的。因為假如es支持的話,es需要對json數(shù)組進行額外處理,整個_bulk流程是下面這樣的

(1) 將良好的json數(shù)組格式解析為JSONArray對象,這個時候,整個json就會在內(nèi)存中出現(xiàn)一份一模一樣的拷貝,一份是json文本,一份是JSONArray對象

(2) 解析出json數(shù)組里的每個json(也就是document)

(3) 對每個請求的document進行路由

(4) 為路由到同一個shard上的多個請求,創(chuàng)建一個請求數(shù)組

(5) 將這個請求數(shù)組序列化

(6) 將序列化后的請求數(shù)組發(fā)送到對應(yīng)的節(jié)點上去

之前提到過bulk size最佳大小的問題,一般建議在幾千條或者10MB左右。所以說可怕的事情來了,假如有100個bulk請求發(fā)送到一個節(jié)點上去,然后每個請求是10MB,100個請求就是1000M=1G,然后每個請求的json都copy一份為JSONArray對象,此時內(nèi)存占用就會翻倍,共占用2G內(nèi)存,甚至不止,因為弄成JSONArray之后,還可能會搞一些其它的數(shù)據(jù)結(jié)構(gòu),就會占用2G+的內(nèi)存。

占用更多的內(nèi)存可能就會積壓內(nèi)存,影響其它請求的內(nèi)存使用量,比如說最重要的搜索請求、搜索請求等等,此時就可能導致其它請求的性能急速下降。

另外,占用內(nèi)存更多,也會導致java虛擬機的垃圾回收次數(shù)更頻繁,每次要回收的垃圾對象更多,耗費時間更多,導致es的java虛擬機阻塞工作線程的時間更多

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"} }

這樣做有什么好處呢?我們來看下整個_bulk流程

(1) 不用將其轉(zhuǎn)換為json對象,不會出現(xiàn)內(nèi)存中相同數(shù)據(jù)的拷貝,直接按照換行符切割json

(2) 對每兩個一組的json,讀取meta,進行document路由

(3) 直接將對應(yīng)的json發(fā)送到node上去

其最大優(yōu)勢在于,不需要講json數(shù)組解析為一個JSONArray對象,形成一份大數(shù)據(jù)的拷貝,浪費內(nèi)存空間,盡可能地保證性能

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容