本篇主要介绍增量更新(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架构社区