日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

Elasticsearch系列---增量更新原理及优势

發(fā)布時間:2023/12/13 综合教程 29 生活家
生活随笔 收集整理的這篇文章主要介紹了 Elasticsearch系列---增量更新原理及优势 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

概要

本篇主要介紹增量更新(partial update,也叫局部更新)的核心原理,介紹6.3.1版本的Elasticsearch腳本使用實例和增量更新的優(yōu)勢。

增量更新過程與原理

簡單回顧

前文我們有簡單介紹過增量的語法,簡單回顧一下請求示例:

POST /music/children/1/_update
{
  "doc": {
    "length": "76"
  }
}

一般從客戶端到Elasticsearch,完整的應(yīng)用請求流程基本是這樣的:

客戶端先發(fā)起GET請求,獲取到document信息,展現(xiàn)到前端頁面上,供用戶進(jìn)行編輯。
用戶編輯完數(shù)據(jù)后,點擊提交。
后臺系統(tǒng)處理修改后的數(shù)據(jù),并組裝好完整的document報文。
發(fā)送PUT請求到ES,進(jìn)行全量替換。
ES將老的document標(biāo)記為deleted,然后重新創(chuàng)建一個新的document。

Elasticsearch的document是基于不可變模式設(shè)計的,所有的document更新,其實都創(chuàng)建了一個新的document出來,再把老的document標(biāo)記為deleted,增量更新也不例外,只是GET全量document數(shù)據(jù),整合新的document,替換老的document這三步操作全在一個shard里完成,毫秒級完成。

增量更新分片之間的交互

增量更新document的步驟:

Java客戶端向ES集群發(fā)送更新請求。
Coodinate Node收到請求,但該document不在當(dāng)前node上,它將請求轉(zhuǎn)發(fā)到Node2節(jié)點的P0 shard上。
Node 2檢索document,修改_source下的JSON,并且重新索引該document,如果有其他線程修改過該document,有版本沖突的話,會重新嘗試更新document,最大重試retry_on_conflict次,超出重試次數(shù)后放棄。
如果步驟3操作成功,Node2會將該document的完整內(nèi)容異步轉(zhuǎn)發(fā)到Node1和Node3的replica shard,重新建立索引。一旦所有replica都返回成功,Node2返回成功消息給Coodinate Node。
Coodinate Node響應(yīng)更新成功消息給客戶端,此時ES集群內(nèi)primary shard和replica shard都已經(jīng)更新完成。

注意幾點:

primary shard向replica shard進(jìn)行document數(shù)據(jù)同步時,發(fā)送的是document的完整信息,因為異步請求不保證有序,如果發(fā)增量信息的話,順序錯亂會導(dǎo)致document內(nèi)容錯誤。
只要Coodinate Node向Java客戶端響應(yīng)成功,就表示所有的primary shard向replica shard都完成了更新操作,此時ES集群內(nèi)的數(shù)據(jù)是一致的,更新是安全的。
retry策略,ES再次獲取document數(shù)據(jù)和最新版本號,成功就更新,失敗再試,最大次數(shù)可以設(shè)置,如5次:retry_on_conflict=5
retry策略在增量操作無關(guān)順序的場景更適用,比如說計數(shù)操作,誰先執(zhí)行誰后執(zhí)行,關(guān)系不大,最終結(jié)果是對的就行。其他的一些場景,如庫存的變化,賬戶余額的變化,直接更新成指定數(shù)值的,肯定不能使用retry策略,但可以轉(zhuǎn)化成加減法,如下單時由直接更新庫存數(shù)量的邏輯改成“當(dāng)前可用庫存數(shù)量=庫存數(shù)量-訂單商品數(shù)量”,賬戶余額的更新加減變化的金額,這樣可以在一定程度上,把順序有關(guān)轉(zhuǎn)化成順序無關(guān),就可以更方便的使用retry策略解決沖突的問題。

增量更新的優(yōu)點

所有的查詢、修改和回寫操作,都是在ES內(nèi)部完成的,減小了網(wǎng)絡(luò)數(shù)據(jù)傳輸開銷(2次),提升了性能。
相比全量替換的時間間隔(秒級以上),縮短了查詢和修改的時間間隔(毫秒級),可以有效降低并發(fā)沖突的情況。

使用腳本實現(xiàn)增量更新

Elasticsearch支持使用腳本實現(xiàn)更為靈活的邏輯,6.0版本以后,默認(rèn)支持的腳本是painless,并且不再支持Groovy,因為Groovy編譯有一定概率會出現(xiàn)內(nèi)存不釋放,最終導(dǎo)致Full GC的問題。

我們以英文兒歌的案例為背景,假設(shè)document的數(shù)據(jù)是這樣:

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

內(nèi)置腳本

現(xiàn)在有這樣一個需求:每當(dāng)有人點擊播放一次歌曲時,該document的likes field就自增1,我們可以用簡單的腳本來實現(xiàn):

POST /music/children/2/_update
{
   "script" : "ctx._source.likes++"
}

執(zhí)行一次后,再查詢該document,發(fā)現(xiàn)likes變成1,每執(zhí)行一次,likes都自增1,結(jié)果符合預(yù)期。

外部腳本

對剛剛那個自增需求做一些改動,支持批量更新播放量,自增的數(shù)量由參數(shù)傳入,腳本也可以通過導(dǎo)入的方式,預(yù)先編譯存儲在ES中,使用的時候調(diào)用即可。

創(chuàng)建腳本
POST _scripts/music-likes
{
  "script": {
    "lang": "painless",
    "source": "ctx._source.likes += params.new_likes" 
  }
}

腳本ID為music-likes,參數(shù)為new_likes,是可以在調(diào)用時傳入的。

使用腳本

我們更新時,執(zhí)行如下請求,就可以調(diào)用剛剛創(chuàng)建的腳本

POST /music/children/2/_update
{
  "script": {
    "id": "music-likes", 
    "params": {
      "new_likes": 2
    }
  }
}

id即創(chuàng)建腳本時的music-likes,params是固定寫法,里面的參數(shù)為new_likes,執(zhí)行后再查看document信息,可以看到likes field的值按傳入的值進(jìn)行累加,結(jié)果符合預(yù)期。

查看腳本

命令:

GET _scripts/music-likes

斜杠后面的參數(shù)即腳本ID

刪除腳本

命令:

DELETE _scripts/music-likes

斜杠后面的參數(shù)即腳本ID

腳本注意事項

ES檢測到新腳本時,會執(zhí)行腳本編譯,并將它存儲在緩存中,編譯比較耗時。
腳本的編寫能參數(shù)化的,就不要硬編碼,提高腳本的復(fù)用性。
短時間內(nèi)太多的腳本編譯,如果超出了ES的承受范圍,ES直接報circuit_breaking_exception錯誤,這個范圍默認(rèn)是15條/分鐘。
腳本緩存默認(rèn)100條,默認(rèn)不設(shè)過期時間,每個腳本最大字符65535字節(jié),想自行配置的話可以改script.cache.expire、script.cache.max_size和script.max_size_in_bytes參數(shù)。

一句話,提高腳本的復(fù)用性。

upsert語法

像剛剛的案例,實現(xiàn)的是一個播放計數(shù)器的功能,目前這個計數(shù)器是與內(nèi)容存儲在一起,如果計數(shù)器單獨存儲,可能會出現(xiàn)新上架的一首歌,但計數(shù)器的document可能還不存在,試圖對它做更新操作會報document_missing_exception錯誤,這種場景我們需要使用upsert語法:

POST /music/children/3/_update
{
   "script" : "ctx._source.likes++",
   "upsert": {
     "likes": 0
   }
}

如果id為3的記錄不存在,第一次請求時,執(zhí)行upsert里面的JSON內(nèi)容,初始化一個新文檔,ID為3,likes值為0;第二次請求時,文檔已經(jīng)存在,此時做script腳本的更新操作,likes自增。

小結(jié)

本篇簡單介紹了增量更新的過程與原理,并與全量替換做了簡單的對比,針對一些簡單的計數(shù)場景,引入腳本的實現(xiàn)方式案例,腳本可以實現(xiàn)很豐富的功能,具體可以查看官網(wǎng)對Painless的介紹。

專注Java高并發(fā)、分布式架構(gòu),更多技術(shù)干貨分享與心得,請關(guān)注公眾號:Java架構(gòu)社區(qū)

總結(jié)

以上是生活随笔為你收集整理的Elasticsearch系列---增量更新原理及优势的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。