PUT /index/type/id,创建文档&替换文档,都是一样的语法
一般对应到应用程序中,每次的执行流程基本是这样的:
(1)应用程序先发起一个get请求,获取到document,展示到前台界面,供用户查看和修改 (2)用户在前台界面修改数据,发送到后台 (3)后台代码,会将用户修改的数据在内存中进行执行,然后封装好修改后的全量数据 (4)发送PUT请求,到es中,进行全量替换 (5)es将老的document标记为deleted,然后重新创建一个新的document
partial update
post /index/type/id/_update
{
"doc": {
"要修改的少数几个field即可,不需要全量的数据"
}
}
看起来,好像就比较方便了,每次就传递少数几个发生修改的field即可
,直接将修改的数据filed更新到document中就完成了修改,不需要将全量的document数据发送过去
2、图解partial update实现原理以及其优点partial update,看起来很方便的操作,实际内部的原理是什么样子的,然后它的优点是什么
全量修改先要查询document的有哪些filed,因为修改要将全量的document数据发送过去,查询、修改操作在java应用中进行
并不需要知道document的有哪些filed,只修改指定发生变化的filed即可,查询、修改操作是在shard中进行
将原来的document标记为deleted,将修改后的数据写到一个新的document中
其实ES内部对partial update的工作原理和全量替换方式是几乎一样的
都是
1获取document
2将传过来的filed更新到document的json中
3将老的document标记为deleted
4将修改后的数据写到新的document中。
partial update相较于全量替换的优点1所有的查询、修改和写回操作,都发生在es中的一个shard内部,避免了所有的网络数据传输的开销(减少2次网络请求),大大提高了性能
全量替换需要读取到java应用中,必然会有网络数据传输。
2减少了查询和修改中的时间间隔,可以有效减少并发冲突的情况
用户修改数据可能需要几分钟或者更长时间,才写回,那么es中的数据可能已经被别的用户修改了,那么就出现了并发冲突
partial update的查询、修改、写回都是发生在shard的内部,一瞬间就完成了,是毫秒级别的,所以大大减少并发冲突的情况
实战演练partial update创建一个document
PUT /test_index/test_type/10
{
"test_field1": "test1",
"test_field2": "test2"
}
响应结果
{
"_index": "test_index",
"_type": "test_type",
"_id": "10",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"created": true
}
partial update
POST /test_index/test_type/10/_update
{
"doc": {
"test_field2": "updated test2"
}
}
响应结果
{
"_index": "test_index",
"_type": "test_type",
"_id": "10",
"_version": 2,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
}
}
查看
GET /test_index/test_type/10
响应结果
{
"_index": "test_index",
"_type": "test_type",
"_id": "10",
"_version": 2,
"found": true,
"_source": {
"test_field1": "test1",
"test_field2": "updated test2"
}
}
3、partial update内置乐观锁并发控制
(1)partial update内置乐观锁并发控制
正常的情况,ES集群中的某个shard:
另一个线程也在做partial update,加入这个线程先将数据先写回去了
两个线程读取的document的version版本号都是1,此时线程B先修改数据成功,document中的version变为2,那么线程A再想修改数据,比较version不相等,修改数据失败,会自动partial update fail
修改失败,可以使用retry策略,retry_on_conflict表示会重新尝试,并指定重试的次数
post /index/type/id/_update?retry_on_conflict=5
retry策略
1再次获取document的数据和罪行版本号
2基于最新版本号再次去更新,
3如果还是失败,重复1、2两个步骤,重试最大次数可以通过retry_on_conflict指定