16图解partial update实现原理

本文详细介绍了Elasticsearch中的partial update操作,它允许仅更新文档的部分字段,避免全量替换带来的网络传输开销和并发冲突。partial update内部原理与全量替换相似,涉及文档的标记删除和新文档创建。通过实战演练展示了如何执行partial update并检查结果。此外,partial update内置乐观锁机制,当并发冲突发生时,可通过`retry_on_conflict`参数进行重试,提高数据一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、什么是partial update?

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应用中进行

image-20211105075106686

partial update局部修改

并不需要知道document的有哪些filed,只修改指定发生变化的filed即可,查询、修改操作是在shard中进行

image-20211105075213404

partial update在ES内部工作原理

image-20211105075723295

将原来的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:

image-20211105215037939

另一个线程也在做partial update,加入这个线程先将数据先写回去了

image-20211105215607751

两个线程读取的document的version版本号都是1,此时线程B先修改数据成功,document中的version变为2,那么线程A再想修改数据,比较version不相等,修改数据失败,会自动partial update fail

image-20211105215839406

(2)retry_on_conflict

修改失败,可以使用retry策略,retry_on_conflict表示会重新尝试,并指定重试的次数

post /index/type/id/_update?retry_on_conflict=5

retry策略

1再次获取document的数据和罪行版本号

2基于最新版本号再次去更新,

3如果还是失败,重复1、2两个步骤,重试最大次数可以通过retry_on_conflict指定

### Django REST Framework 中 `partial_update` 的用法和实现 在 Django REST Framework (DRF) 中,`partial_update` 方法用于处理部分更新请求。当客户端发送 PATCH 请求来修改资源的部分字段时,服务器端会调用此方法。 #### 使用示例 为了展示如何使用 `partial_update`,考虑一个简单的博客文章模型及其对应的序列化器: ```python from rest_framework import serializers, viewsets from .models import BlogPost class BlogPostSerializer(serializers.ModelSerializer): class Meta: model = BlogPost fields = ['id', 'title', 'content'] class BlogPostViewSet(viewsets.ModelViewSet): queryset = BlogPost.objects.all() serializer_class = BlogPostSerializer def partial_update(self, request, *args, **kwargs): kwargs['partial'] = True return super().update(request, *args, **kwargs) ``` 在这个例子中,通过设置 `kwargs['partial'] = True` 并调用父类的 `update()` 方法实现了对现有记录的部分更新功能[^1]。 对于视图集中的默认行为来说,只需继承自 `ModelViewSet` 即可获得完整的 CRUD 功能支持,包括 `partial_update` 操作。如果需要定制逻辑,则可以重写该方法并传递参数 `partial=True` 给基类的方法以指示这是一个局部更新操作[^2]。 #### 实现细节 具体到 DRF 内部是如何工作的呢?当接收到 HTTP PATCH 请求后,框架内部会创建一个新的实例对象并将传入的数据映射至相应的属性上。接着它会尝试验证这些新值是否满足约束条件——这一步骤涉及到前面提到过的 `validate_<field_name>` 验证钩子函数[^3]。一旦所有必要的校验都成功完成之后,才会真正保存更改后的实体回数据库里去。 需要注意的是,在做部分更新的时候,默认情况下不会清除未提交的新值的那些字段;也就是说只有被指定要改变的内容会被覆盖掉而已[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

失业找工作中

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值