本篇主要介紹增量更新(partial update,也叫局部更新)的核心原理,介紹6.3.1版本的Elasticsearch腳本使用實例和增量更新的優點。前端
前文咱們有簡單介紹過增量的語法,簡單回顧一下請求示例:node
POST /music/children/1/_update
{
"doc": {
"length": "76"
}
}複製代碼
通常從客戶端到Elasticsearch,完整的應用請求流程基本是這樣的:緩存
Elasticsearch的document是基於不可變模式設計的,全部的document更新,其實都建立了一個新的document出來,再把老的document標記爲deleted,增量更新也不例外,只是GET全量document數據,整合新的document,替換老的document這三步操做全在一個shard裏完成,毫秒級完成。安全
增量更新document的步驟:markdown
Elasticsearch支持使用腳本實現更爲靈活的邏輯,6.0版本之後,默認支持的腳本是painless,而且再也不支持Groovy,由於Groovy編譯有必定機率會出現內存不釋放,最終致使Full GC的問題。網絡
咱們以英文兒歌的案例爲背景,假設document的數據是這樣:架構
{
"_index": "music",
"_type": "children",
"_id": "2",
"_version": 6,
"found": true,
"_source": {
"name": "wake me, shark me",
"content": "don't let me sleep too late, gonna get up brightly early in the morning",
"language": "english",
"length": "55",
"likes": 0
}
}複製代碼
如今有這樣一個需求:每當有人點擊播放一次歌曲時,該document的likes field就自增1,咱們能夠用簡單的腳原本實現:併發
POST /music/children/2/_update
{
"script" : "ctx._source.likes++"
}複製代碼
執行一次後,再查詢該document,發現likes變成1,每執行一次,likes都自增1,結果符合預期。less
對剛剛那個自增需求作一些改動,支持批量更新播放量,自增的數量由參數傳入,腳本也能夠經過導入的方式,預先編譯存儲在ES中,使用的時候調用便可。異步
POST _scripts/music-likes
{
"script": {
"lang": "painless",
"source": "ctx._source.likes += params.new_likes"
}
}複製代碼
腳本ID爲music-likes,參數爲new_likes,是能夠在調用時傳入的。
咱們更新時,執行以下請求,就能夠調用剛剛建立的腳本
POST /music/children/2/_update
{
"script": {
"id": "music-likes",
"params": {
"new_likes": 2
}
}
}複製代碼
id即建立腳本時的music-likes,params是固定寫法,裏面的參數爲new_likes,執行後再查看document信息,能夠看到likes field的值按傳入的值進行累加,結果符合預期。
命令:
GET _scripts/music-likes複製代碼
斜槓後面的參數即腳本ID
命令:
DELETE _scripts/music-likes複製代碼
斜槓後面的參數即腳本ID
一句話,提升腳本的複用性。
像剛剛的案例,實現的是一個播放計數器的功能,目前這個計數器是與內容存儲在一塊兒,若是計數器單獨存儲,可能會出現新上架的一首歌,但計數器的document可能還不存在,試圖對它作更新操做會報documentmissingexception錯誤,這種場景咱們須要使用upsert語法:
POST /music/children/3/_update
{
"script" : "ctx._source.likes++",
"upsert": {
"likes": 0
}
}複製代碼
若是id爲3的記錄不存在,第一次請求時,執行upsert裏面的JSON內容,初始化一個新文檔,ID爲3,likes值爲0;第二次請求時,文檔已經存在,此時作script腳本的更新操做,likes自增。
本篇簡單介紹了增量更新的過程與原理,並與全量替換作了簡單的對比,針對一些簡單的計數場景,引入腳本的實現方式案例,腳本能夠實現很豐富的功能,具體能夠查看官網對Painless的介紹。
專一Java高併發、分佈式架構,更多技術乾貨分享與心得,請關注公衆號:Java架構社區